2013-08-08 27 views
7

Tôi gặp sự cố phát sinh các vùng tên lồng nhau và các lớp được tạo khuôn mẫu. Tôi cũng có thể tạo ra trường hợp thử nghiệm tạo ra lỗi giống như mã thực tế, nhưng có thể đọc được nhiều hơn một chút.Không gian tên được lồng và biểu tượng mơ hồ

Biên dịch đoạn mã sau sử dụng VS2012 với nền tảng công cụ 2010 gây ra một lỗi:

namespace A 
{ 
    namespace B 
    { 
     namespace C1 
     { 
     struct SMeasResult{}; 
     } 
     namespace C2 
     { 
     struct SMeasResult{}; 
     } 
    } 
} 

namespace C1Test 
{ 
    using namespace A::B::C1; 

    template<typename T> 
    class Fook 
    { 
    public: 

     void Yu() 
     { 
     SMeasResult Field; 
     } 
    }; 
} 

namespace C2Test 
{ 
    using namespace A::B::C2; 

    template<typename T> 
    class Fook 
    { 
    public: 

     void Yu() 
     { 
     SMeasResult Field; 
     } 
    }; 
} 

void m(){ 
    C1Test::Fook<int> yu; 
    C2Test::Fook<int> me; 

    yu.Yu(); 
    me.Yu(); 
} 

Các lỗi cụ thể như sau:

1>------ Build started: Project: MultiVicomTest (Visual Studio 2010), Configuration: Debug Win32 ------ 
1> test.cpp 
1>c:\code\test.cpp(27): warning C4101: 'Field' : unreferenced local variable 
1>   c:\code\test.cpp(26) : while compiling class template member function 'void C1Test::Fook<T>::Yu(void)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   c:\code\test.cpp(49) : see reference to class template instantiation 'C1Test::Fook<T>' being compiled 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>c:\code\test.cpp(43): error C2872: 'SMeasResult' : ambiguous symbol 
1>   could be 'c:\code\test.cpp(11) : A::B::C2::SMeasResult' 
1>   or  'c:\code\test.cpp(7) : A::B::C1::SMeasResult' 
1>   c:\code\test.cpp(42) : while compiling class template member function 'void C2Test::Fook<T>::Yu(void)' 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>   c:\code\test.cpp(50) : see reference to class template instantiation 'C2Test::Fook<T>' being compiled 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

Tôi không hiểu tại sao biểu tượng 'SMeasResult' sẽ không rõ ràng đối với trình biên dịch, vì nó được sử dụng trong một không gian tên riêng biệt. Những gì tôi có thể tìm ra cho đến nay, là vấn đề này chỉ xuất hiện khi các lớp học được các lớp templated. Vấn đề tương tự không xuất hiện khi định nghĩa mẫu được loại bỏ.

Ai có thể cho tôi biết nếu tôi đã làm điều gì sai?

+1

Tôi chắc chắn đây là lỗi. Gcc và clang biên dịch điều này tốt và tôi không thể thấy tại sao nó sẽ mơ hồ, một trong hai. – jrok

+1

MSVC chưa bao giờ triển khai tra cứu hai giai đoạn cho các tên được sử dụng trong các khuôn mẫu theo yêu cầu của các tiêu chuẩn ngôn ngữ kể từ C++ 98. Lỗi này rất có thể là hậu quả của nó. – Casey

Trả lời

2

Điều này thực sự trông giống như lỗi trình biên dịch đối với tôi. Khi bạn xem xét phiên bản C1Test của hàm được biên dịch mà không có sự mơ hồ, tôi nghi ngờ rằng không gian tên sử dụng nào đó trong vòng namespace C1Test đang kéo dài ngay cả vào không gian tên C2Test.

Điều này được chứng thực thêm bởi thực tế là g ++ 4.4 và 4.5 có thể biên dịch mã này tốt.

+1

Đúng, việc sử dụng bị rò rỉ trên hình ảnh chứ không phải trong g ++. Vì tôi không phải là một fan hâm mộ lớn của từ khóa này, tôi không biết những gì các tiêu chuẩn đang nói về điều này. – Uman

+1

Thật thú vị, sắp xếp lại mã với không gian tên 'C2Test' trước khi kết quả' C1Test' trong "sự mơ hồ" * vẫn đang được báo cáo cho 'SMeasResult' bên trong' C2Test'. Thực tế là việc khai báo trong 'C1' xuất hiện trước khi' C2' có vẻ quan trọng hơn thứ tự của các sử dụng. – Casey

+0

Lỗi của tôi - đó là thứ tự của các mẫu instantiations có ý nghĩa, không phải bất kỳ khai báo nào. Mẫu thứ hai được khởi tạo được "đổ lỗi" cho lỗi bất kể thứ tự khai báo của 'C1',' C2', 'C1Test' hoặc' C2Test'. – Casey

0

Hãy thử sử dụng sử dụng A :: B :: C1 :: SMeasResult; và sử dụng A :: B :: C2 :: SMeasResult; trong các không gian tên C1Test và C2Test của bạn. Điều này giải quyết vấn đề.

BTW Tại sao bạn cần quá nhiều không gian tên? STL là rất lớn, nhưng nó chỉ sử dụng 1 không gian tên - std.

+0

Boost cũng lớn và nó sử dụng rất nhiều không gian tên;) –

+0

Trong trường hợp cụ thể này, chúng tôi có một codebase lớn chứa mã liên quan đến các loại công nghệ vô tuyến khác nhau. Chúng tôi muốn di chuyển các lớp tương ứng vào các không gian tên giống với công nghệ mà chúng đại diện, do đó cần nhiều không gian tên. Do tích hợp nhiều nền tảng khác (.NET, Java), chúng tôi đã chọn một cách tương tự với chúng (chỉ cần nghĩ về số lượng không gian tên khổng lồ trong các nền tảng đó). – Simon

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