2015-05-20 29 views
8

Hãy xem xét các testcase sau (giảm từ nguồn LLVM):std :: make_unique, không gian tên vô danh và ODR

//% cat foo1.cpp 

#include <memory> 
namespace { 
class A { 
    int i; 
}; 
} 
class G { 
    std::unique_ptr<A> foo() const; 
}; 
std::unique_ptr<A> G::foo() const { return std::make_unique<A>(); } 

//% cat foo2.cpp 

#include <memory> 
namespace { 
class A { 
    bool a; 
}; 
} 
class H { 
    std::unique_ptr<A> bar() const; 
}; 
std::unique_ptr<A> H::bar() const { return std::make_unique<A>(); } 

Điều này vi phạm các Rule Một Definition?

gcc-6 hiện đang nghĩ như vậy:

~ % g++ -flto -shared -std=c++14 foo1.cpp foo2.cpp 

/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:187:72: warning: type ‘struct _Base’ violates one definition rule [-Wodr] 
     typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base; 
                     ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:187:72: note: a different type is defined in another translation unit 
     typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base; 
                     ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:147:13: note: the first difference of corresponding definitions is field ‘_M_head_impl’ 
     _Head _M_head_impl; 
      ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:147:13: note: a field of same name but different type is defined in another translation unit 
     _Head _M_head_impl; 
      ^
foo1.cpp:3:7: note: type ‘struct A’ defined in anonymous namespace can not match type ‘struct A’ 
class A { 
     ^
foo2.cpp:3:7: note: the incompatible type defined in anonymous namespace in another translation unit 
class A { 
     ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: warning: type ‘struct _Inherited’ violates one definition rule [-Wodr] 
     typedef _Tuple_impl<0, _T1, _T2> _Inherited; 
             ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: note: a type with the same name but different base type is defined in another translation unit 
     typedef _Tuple_impl<0, _T1, _T2> _Inherited; 
             ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: type ‘struct _Head_base’ defined in anonymous namespace can not match type ‘struct _Head_base’ 
    struct _Head_base<_Idx, _Head, false> 
      ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: the incompatible type defined in anonymous namespace in another translation unit 
    struct _Head_base<_Idx, _Head, false> 
      ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/bits/unique_ptr.h:151:41: warning: type ‘struct element_type’ violates one definition rule [-Wodr] 
     typedef _Tp      element_type; 
             ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/bits/unique_ptr.h:151:41: note: a different type is defined in another translation unit 
     typedef _Tp      element_type; 
             ^
foo1.cpp:4:7: note: the first difference of corresponding definitions is field ‘i’ 
    int i; 
     ^
foo2.cpp:4:8: note: a field with different name is defined in another translation unit 
    bool a; 
     ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: warning: type ‘struct _Inherited’ violates one definition rule [-Wodr] 
     typedef _Tuple_impl<0, _T1, _T2> _Inherited; 
             ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: note: a type with the same name but different base type is defined in another translation unit 
     typedef _Tuple_impl<0, _T1, _T2> _Inherited; 
             ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: type ‘struct _Head_base’ defined in anonymous namespace can not match type ‘struct _Head_base’ 
    struct _Head_base<_Idx, _Head, false> 
      ^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: the incompatible type defined in anonymous namespace in another translation unit 
    struct _Head_base<_Idx, _Head, false> 
     ^
+0

Điều này vẫn xảy ra nếu bạn cung cấp cho các không gian tên bao quanh tên 'A', như 'Bob' và' Cô bé Lọ Lem'? – Yakk

+0

No. Sử dụng các không gian tên có tên hoạt động tốt. Trông giống như một lỗi trình biên dịch đối với tôi. – octoploid

Trả lời

6

Đây là lỗi GCC (đã có trong cây phát trong vài ngày). Vấn đề đã được gây ra bởi một sửa chữa mà làm cho GCC để xem xét typedefs ngầm vô danh và do đó các cấu trúc bên ngoài có loại sáp nhập (không chính xác như vậy). Các testcase là cố định bây giờ, tôi sẽ được quan tâm để nghe về nhiều cảnh báo có thể xuất hiện không có thật.

+0

Cảm ơn. BTW Tôi quên đề cập đến vấn đề được theo dõi ở đây: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66180 – octoploid

-2

Bạn có hai định nghĩa khác nhau của một lớp. Biên dịch hai kết quả cùng nhau trong một cuộc xung đột trực tiếp trừ khi hai kết quả này nằm trong các không gian tên riêng biệt. Tôi cho rằng điều này có thể đúng.

Điều bạn có thể muốn tìm là liệu hai tính năng triển khai có loại trừ lẫn nhau hay không. Có thể có hai tệp nguồn khác nhau có định nghĩa riêng, nhưng có trường hợp có hai định nghĩa có thể có ý nghĩa (nghĩa là tôi có API luồng trên Windows và Linux và tôi cần có hai định nghĩa khác nhau dựa trên cài đặt biên dịch của mình).

+11

Không gian tên chưa đặt tên sẽ làm cho các định nghĩa này trở nên duy nhất trong toàn bộ chương trình. – myaut

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