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?
-
Das Problem ist relativ eindeutig. Durch
using namespace boost;
wird der Namensraumboost
in den globalen Namensraum eingebunden. Dadurch werden verschiedene zusätzlicheoperator ==
zur Verfügung gestellt. Anscheinend findet der Kompiler dann einen besser passendenoperator ==
, als welchen du möchtest. Also wird der falscheoperator ==
instanziert, welcher einboost::re_detail::regex_iterator_traits
beinhaltet. Diese Klasse ist vonstd::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 einusing 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 Namensraumboost
keinen besser passendenoperator ==
. Der Namensraum ist allerdings auch verdammt gross, kann gut sein, dass ich beim Suchen den einen oder anderenoperator ==
ü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