2009-07-16 14 views
7

Tôi không thể hiểu tại sao đoạn mã này không biên dịch:Namespace đụng độ trong C++

namespace A { 
     class F {};    // line 2 
     class H : public F {}; 
} 

namespace B { 
     void F(A::H x);   // line 7 
     void G(A::H x) { 
       F(x);   // line 9 
     } 
} 

Tôi đang sử dụng gcc 4.3.3, và lỗi này là:

s3.cpp: In function ‘void B::G(A::H)’: 
s3.cpp:2: error: ‘class A::F’ is not a function, 
s3.cpp:7: error: conflict with ‘void B::F(A::H)’ 
s3.cpp:9: error: in call to ‘F’ 

Tôi nghĩ rằng bởi vì trong dòng 9 không có tiền tố không gian tên, F(x) chỉ có nghĩa là B::F(x). Trình biên dịch cố gắng để đúc x vào lớp cha của chính nó. Theo hiểu biết của tôi thì không nên. Tại sao nó làm điều đó?

Trả lời

11

Đó là do trình biên dịch sẽ tìm kiếm chức năng trong cùng một không gian tên đối số của nó từ. Trình biên dịch tìm thấy ở đó A::F số nhận dạng nhưng nó không phải là một hàm. Kết quả là bạn sẽ gặp lỗi.

Đó là hành vi tiêu chuẩn theo như tôi có thể nhớ.

3.4.2 Đối số phụ thuộc vào tra cứu tên Khi một cái tên không đủ tiêu chuẩn được sử dụng như postfix-biểu trong một cuộc gọi chức năng (5.2.2), không gian tên khác không được coi là trong tra cứu không đủ tiêu chuẩn thông thường (3.4. 1) có thể được tìm kiếm, và khai báo chức năng người bạn phạm vi không gian tên (11.4) không thể nhìn thấy khác có thể được tìm thấy. Những sửa đổi này cho tìm kiếm phụ thuộc vào các loại đối số (và đối với các mẫu đối số, không gian tên của đối số mẫu).

Đối với mỗi loại đối số T trong cuộc gọi hàm, có một tập hợp không hoặc nhiều không gian tên được liên kết và tập hợp không hoặc nhiều lớp liên kết cần xem xét. Các tập các không gian tên và các lớp được xác định hoàn toàn bởi các kiểu đối số hàm (và không gian tên của bất kỳ đối số mẫu khuôn mẫu nào). Tên typedef và khai báo sử dụng được sử dụng để xác định loại không đóng góp cho tập hợp này. Các bộ không gian tên và các lớp học được xác định theo cách sau ...

Quy tắc này cho phép bạn viết đoạn mã sau:

std::vector<int> x; 
// adding some data to x 
//... 

// now sort it 
sort(x.begin(), x.end()); // no need to write std::sort 

Và cuối cùng: Vì Core Issue 218 một số trình biên dịch sẽ biên dịch mã được đề cập mà không có bất kỳ lỗi nào.

+1

Cái gọi là tra cứu Koenig, trên thực tế, được mô tả trong phần 3.4.2 của tiêu chuẩn C++. –

+0

Sau đó, nếu VS biên dịch, đó là lỗi? – liori

+0

Bạn có thể tìm thấy tham chiếu đến tuyên bố đó không? Tôi chưa bao giờ nghe về bất kỳ quy tắc nào như vậy ... – xtofl

4

Bạn đã thử sử dụng các trình biên dịch khác chưa? Có một gcc bug report ở đây bị treo (bất kể điều đó có nghĩa là gì).

EDIT: Sau một số nghiên cứu, tôi đã tìm thấy điều này more official bug.

+0

Đây là một ví dụ tối thiểu về mã của riêng tôi mà biên dịch trên VS2005 của bạn tôi. Tôi đã không thử nghiệm phần chính xác này mặc dù. Và ... DeusAduro dường như không có vấn đề biên dịch nó trên VS2005. – liori

+0

Báo cáo lỗi trông khá giống như vậy, mặc dù nó liên quan đến các khuôn mẫu, có lược đồ tra cứu khác (hai pha) khác nhau. – xtofl

+0

Lưu ý: những người khác báo cáo VS2005 để biên dịch mã này như mong đợi. Tôi đã thử thử nghiệm của Comeau Drive -> thành công. Chỉ có gcc dường như chịu đựng điều này, có vẻ như vậy. – xtofl

1

Rất kỳ lạ, tôi sao chép và dán trực tiếp đến VS 2005 và tôi nhận được một lỗi, mà tôi mong đợi:

Lỗi 1 lỗi LNK2001: chưa được giải quyết biểu tượng bên ngoài "khoảng trống __cdecl B :: F (lớp A :: H) "

Bởi vì chúng tôi đã không thực sự xác định F (x) trong không gian tên B ... không chắc chắn lý do tại sao Gcc đưa ra lỗi này.

0

Tôi vừa thử biên dịch nó trên Visual Studio 2005 và nó hoạt động tốt. Tôi tự hỏi nếu nó là một thực hiện bị hỏng của Argument Dependent Lookup nơi không gian tên từ các đối số vô tình được đưa vào?