2009-07-10 34 views
6

Trong C++ bạn chỉ định liên kết bên trong bằng cách gói các định nghĩa lớp và hàm của bạn bên trong một không gian tên ẩn danh. Bạn cũng có thể nhanh chóng khởi tạo các khuôn mẫu, nhưng để là các tiêu chuẩn phù hợp với bất kỳ sự khởi tạo rõ ràng nào của các khuôn mẫu phải xảy ra trong cùng một không gian tên. AFAICT này nên biên dịch, nhưng GCC không thành công trên nó:Không gian tên vô danh bao gồm tất cả các không gian tên?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

Với các lỗi:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo') 

Đó là thú vị bởi vì không gian tên vô danh chỉ nên được xác định mối liên hệ, không thực sự hoạt động như một namespace, và không gian tên toàn cầu chắc chắn bao quanh foo, vì nó bao quanh mọi không gian tên. Nhưng ngay cả điều này không làm việc !:

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

nào thất bại với lỗi tương tự, chỉ cần liệt kê các không gian tên toàn cầu thay vì:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::') 

:/

+0

Phiên bản GCC nào - hoặc tùy chọn trình biên dịch nào - hoặc nền tảng nào? Tôi đã thử mẫu đầu tiên với G ++ 4.0.1 trên MacOS X có và không có -Wall và nó được biên dịch mà không có khiếu nại hoặc cảnh báo. –

+0

GCC 4.2 trên Solaris. –

Trả lời

10

Một namespace nặc danh là một cách logic tương đương với

namespace _TU_specific_unique_generated_name 
{ 
    // ... 
} 
using namespace _TU_specific_unique_generated_name; 

Một namespace, nặc danh hoặc cách khác, không ảnh hưởng đến sự liên kết của các thành viên. Đặc biệt các thành viên của một không gian tên vô danh không kỳ diệu có được liên kết nội bộ.

+1

Tôi sẽ thêm rõ ràng, đó là những thứ trong _TU_specific_unique_generated_name không thể được sử dụng bên ngoài tệp. – Valentein

+0

Nó thực sự mô tả cách chính xác này trong tiêu chuẩn, được chấp nhận. –

6

Tôi nghĩ rằng bạn có câu trả lời của bạn - các không gian tên ẩn danh là các không gian tên riêng biệt, độc đáo. BTW, trình biên dịch tạo ra một số số nguyên lớn ngẫu nhiên để biểu diễn không gian tên đó trong nội bộ.

0

Theo Stroustrup (mục 8.2.5.1) không gian tên chung có quyền truy cập vào không gian tên ẩn danh (không tên), nhưng nó không nói rõ ràng.

Tôi hy vọng bạn sẽ phải xác định không gian tên với một tuyên bố sử dụng hoặc hoàn toàn đủ điều kiện tham chiếu đến không gian tên khác bên trong namespace giấu tên ...

7

Đầu tiên: Bạn đang instantiating một cách rõ ràng một lớp mẫu, bạn không xác định một mẫu lớp mới. Điều gì

template class bar<int>; 

nói là "hãy khởi tạo thanh mẫu lớp cho kiểu int tại đây". Bạn không thể làm điều đó trong một không gian tên khác, cũng giống như bạn không thể chuyên biệt hóa một phần mẫu lớp trong một không gian tên khác. Cụ thể, mẫu được khởi tạo rõ ràng phải được xác định và trong ví dụ của bạn, không có (không gian tên ẩn danh) :: thanh <>, chỉ foo :: bar <>.

Thứ hai: Không gian tên ẩn danh là một không gian tên thực (mặc dù vậy, nó cũng khác nhau ở mọi đơn vị dịch). Nó cũng không thay đổi liên kết một cách kỳ diệu. Mọi thứ được khai báo bên trong namespace {} vẫn là liên kết mặc định, giống như ở bất kỳ phạm vi không gian tên nào khác. IIRC, nó thậm chí còn được thêm vào để cho phép các đơn vị dịch-tư nhân, nhưng các đối tượng liên kết bên ngoài.

Các vấn đề liên quan