2015-05-20 5 views
8

Bitte beachten Sie die folgenden Testfall (von LLVM Quelle reduziert):std :: make_unique, anonymen Namespace und 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>(); } 

und

//% 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>(); } 

Enthält diese die Regel eine Definition verletzen?

gcc-6 zur Zeit denkt so:

~ % 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

Tritt dies immer noch auf, wenn Sie die Namespaces mit den Namen 'A', wie' Bob' und 'Cinderella' angeben? – Yakk

+0

Nein. Die Verwendung von benannten Namespaces funktioniert einwandfrei. Sieht für mich mehr wie ein Compiler-Fehler aus. – octoploid

Antwort

6

Das war GCC-Bug (der nur wenige Tage im Entwicklungsbaum war). Das Problem wurde durch eine andere Korrektur verursacht, die GCC veranlasste, implizite typedefs nicht-anonym zu betrachten und somit die äußeren Strukturen typisiert zu bekommen (falsch). Der Testfall ist jetzt behoben, ich wäre an weiteren Warnungen interessiert, die möglicherweise falsch erscheinen.

+0

Danke. Übrigens habe ich vergessen zu erwähnen, dass das Problem hier verfolgt wird: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66180 – octoploid

-2

Sie haben zwei verschiedene Definitionen einer Klasse. Das Kompilieren der beiden führt zu einem direkten Konflikt, wenn diese beiden nicht in separaten Namespaces enden. Ich nehme an, das könnte richtig sein.

Worauf Sie achten sollten, ist, ob sich die beiden Implementierungsfeatures gegenseitig ausschließen. Es kann zwei verschiedene Quelldateien mit separaten Definitionen geben, aber es gibt Fälle, in denen zwei Definitionen sinnvoll sein können (d. H. Ich habe eine Threading-API für Windows und Linux und muss zwei verschiedene Definitionen basierend auf meinen Kompilierungseinstellungen haben).

+11

Unbenannte Namespaces sollten diese Definitionen über das Programm hinweg eindeutig machen. – myaut

Verwandte Themen