Kompilierfehler bei boost::regex (diesmal verstaendlich)



  • Hallo,

    nachdem mein letzter Beitrag offenbar nicht wirklich erhellend war, habe ich versucht, das Problem runterzukochen. Das Problem stellt sich nun wie folgt dar: Ich habe zwei Dateien main.cc

    #include "base_nd.h"
    
    int main(int argc, char** argv)
    {
    
    }
    

    und base_nd.h

    #ifndef BASE_NODE_H
    #define BASE_NODE_H
    
    #include <boost/regex.hpp>
    
    using namespace boost;
    
    template<class N> class Base_Nd;
    template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    
    template<class N> class Base_Nd
    {
    	friend bool operator==<N>(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    };
    
    template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs) { return lhs.id() == rhs.id(); }
    
    class Rev_Nd : public virtual Base_Nd<Rev_Nd> { };
    
    #endif
    

    Wenn ich das kompiliere, erhalte ich die Fehlermeldung

    **** Build of configuration Debug for project GenRecon ****
    
    make all 
    Building file: ../main.cc
    Invoking: GCC C++ Compiler
    g++ -I../../../libs/boost -I../../../libs/gsl/include -I../../../libs/log4cxx/include -I../ -I../src -I../src/classification -I../src/IO -I../src/node -I../src/tree -O0 -g3 -c -fmessage-length=0 -ansi -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cc"
    In file included from ../main.cc:1:
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h: In instantiation of »std::iterator_traits<Rev_Nd>«:
    ../../../libs/boost/boost/regex/v4/iterator_traits.hpp:116:   instantiated from »boost::re_detail::regex_iterator_traits<Rev_Nd>«
    ../src/node/base_nd.h:15:   instantiated from »Base_Nd<Rev_Nd>«
    ../src/node/base_nd.h:22:   instantiated from here
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h:133: Fehler: invalid use of incomplete type »class Rev_Nd«
    ../src/node/base_nd.h:22: Fehler: forward declaration of »class Rev_Nd«
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h:134: Fehler: invalid use of incomplete type »class Rev_Nd«
    ../src/node/base_nd.h:22: Fehler: forward declaration of »class Rev_Nd«
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h:135: Fehler: invalid use of incomplete type »class Rev_Nd«
    ../src/node/base_nd.h:22: Fehler: forward declaration of »class Rev_Nd«
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h:136: Fehler: invalid use of incomplete type »class Rev_Nd«
    ../src/node/base_nd.h:22: Fehler: forward declaration of »class Rev_Nd«
    /usr/include/c++/4.3/bits/stl_iterator_base_types.h:137: Fehler: invalid use of incomplete type »class Rev_Nd«
    ../src/node/base_nd.h:22: Fehler: forward declaration of »class Rev_Nd«
    make: *** [main.o] Fehler 1
    

    Verwendung der folgenden beiden Versionen von base_nd.h fuehrt zu fehlerfreien Kompilieren (einziger Unterschied zum Original besteht in den auskommentierten Zeilen):

    #ifndef BASE_NODE_H
    #define BASE_NODE_H
    
    #include <boost/regex.hpp>
    
    //using namespace boost;
    
    template<class N> class Base_Nd;
    template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    
    template<class N> class Base_Nd
    {
    	friend bool operator==<N>(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    };
    
    template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs) { return lhs.id() == rhs.id(); }
    
    class Rev_Nd : public virtual Base_Nd<Rev_Nd> { };
    
    #endif
    

    und

    #ifndef BASE_NODE_H
    #define BASE_NODE_H
    
    #include <boost/regex.hpp>
    
    using namespace boost;
    
    template<class N> class Base_Nd;
    template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    
    template<class N> class Base_Nd
    {
    	//friend bool operator==<N>(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs);
    };
    
    //template<class N> bool operator==(const Base_Nd<N>& lhs, const Base_Nd<N>& rhs) { return lhs.id() == rhs.id(); }
    
    class Rev_Nd : public virtual Base_Nd<Rev_Nd> { };
    
    #endif
    

    Weiss jemand, was hier das Problem ist?


  • Administrator

    Das Problem ist relativ eindeutig. Durch using namespace boost; wird der Namensraum boost in den globalen Namensraum eingebunden. Dadurch werden verschiedene zusätzliche operator == zur Verfügung gestellt. Anscheinend findet der Kompiler dann einen besser passenden operator == , als welchen du möchtest. Also wird der falsche operator == instanziert, welcher ein boost::re_detail::regex_iterator_traits beinhaltet. Diese Klasse ist von std::iterator_traits abgeleitet und das gibt dann schlussendlich den Kompilerfehler.

    Das grundsätzliche Problem liegt also in deiner unvorsichtigen Verwendung von using namespace . Deswegen warnen hier verschiedene Leute immer wieder vor der unachtsamen Verwendung. Erst recht hat so ein using namespace nichts in einem Header verloren. Diese Anweisung hebelt die Funktion des Namensraumes aus.

    [Unwichtiger Zusatz]
    Mir ist leider nicht ganz klar, wieso der Kompiler hier eine bessere Möglichkeit findet, denn ich selber finde im Namensraum boost keinen besser passenden operator == . Der Namensraum ist allerdings auch verdammt gross, kann gut sein, dass ich beim Suchen den einen oder anderen operator == übersehen habe.
    VC2008 kompiliert den Code einwandfrei, konnte den Fehler nur mit dem g++ reproduzieren. Mir ist nicht ganz klar, ob es ein Bug im g++ ist oder VC2008 sich nicht ganz korrekt an den Standard hält, was ziemlich üblich wäre.
    [/Unwichtiger Zusatz]

    Grüssli


Log in to reply