2012-05-01 27 views
7

Không nên hoạt động trong một không gian tên chỉ bằng cách sử dụng phạm vi không gian tên hoặc bằng chỉ thị sử dụng?Tại sao một số chức năng trong không gian tên có thể truy cập được nếu không có tiền tố phạm vi không gian tên?

Tôi gặp sự cố trong đó một số hàm nhất định được xác định bên trong không gian tên, có thể truy cập BÊN NGOÀI của không gian tên đó. Tôi tin rằng cần có một lỗi trình biên dịch, nhưng tôi không nhận được một trong ba trình biên dịch khác nhau tôi đã thử (VS.NET 2003, VS2010 và GCC 4).

Đây là mã:

namespace N{ 
    typedef struct _some_type *some_type; 
    struct some_struct { int x; }; 
    void A(void); 
    void B(int); 
    void C(some_type*); 
    void D(some_type); 
    void E(struct some_struct); 
} 

using N::some_type; 
using N::some_struct; 

void TestFunction() 
{ 
    some_type foo; 
    some_struct s; 

    N::A();   //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    A();   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::B(0);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    B(0);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 

    N::C(&foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::C(&foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    C(&foo);  //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::D(foo);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::D(foo);  //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    D(foo);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 

    N::E(s);  //should compile (and does on VS2003, VS2010, and GCC 4.1.2) 
    ::E(s);   //shouldn't compile (and doesn't on VS2003, VS2010, and GCC 4.1.2) 
    E(s);   //shouldn't compile (but does on VS2003, VS2010, and GCC 4.1.2) -- problem! 
} 

Không ai trong số các chức năng nên có thể truy cập mà không sử dụng N :: tiền tố, nhưng C, D, và E là vì một lý do không rõ. Ban đầu tôi nghĩ rằng đó là một lỗi trình biên dịch, nhưng vì tôi thấy điều này qua nhiều trình biên dịch nó làm cho tôi đặt câu hỏi những gì đang xảy ra.

+0

Tôi nghĩ đây là lỗi "trình biên dịch cũ", nhưng cũng biên dịch trên gcc 4.6. – mfontanini

+0

Tôi đoán tốt nhất là bạn có các dòng này: 'using N :: some_type;' và 'sử dụng N :: some_struct;' và kiểu trả về của C, D, và E là các kiểu đó. – gcochard

+0

Greg, bạn có thể loại bỏ các sử dụng và nó vẫn xảy ra. Ngoài ra các kiểu trả về của tất cả các hàm đều bị vô hiệu. – syplex

Trả lời

10

Tôi nghĩ bạn đang thấy ảnh hưởng của Koenig lookup. Trong ví dụ của bạn, foos là các loại được xác định trong không gian tên N. Các cuộc gọi đến các thói quen C, DE sử dụng các đối số của các loại đó, do đó, không gian tên N được tìm kiếm để giải quyết các cuộc gọi chức năng đó.

+3

Lưu ý phụ: Thêm dấu ngoặc đơn, tức là '(C) (& foo)' sẽ ngăn tra cứu phụ thuộc vào đối số. –

+0

Vâng, bạn đã đúng. Đó là trong phần 3.4.2 của thông số C++ 2003. Tôi tình cờ không đồng ý với phần này của thông số kỹ thuật và nghĩ rằng nó đã bị ảnh hưởng, nhưng có nó. Có ai biết nếu có một cách để buộc một phạm vi không gian tên nghiêm ngặt hơn trong GCC hoặc VC + +? – syplex

+0

@syplex Trong thực tế, nó cực kỳ hữu ích cho việc tìm kiếm các hàm miễn phí đúng cách dựa trên các kiểu đối số bên trong các khuôn mẫu. Tôi không nghĩ rằng g ++ cung cấp một tùy chọn như nó sẽ đi ngược lại những gì theo yêu cầu của tiêu chuẩn. Vấn đề * thực * bạn đang cố giải quyết ở đây là gì? –

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