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> { }; #endifWenn 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 1Verwendung 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> { }; #endifund
#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> { }; #endifWeiss jemand, was hier das Problem ist?
-
Das Problem ist relativ eindeutig. Durch
using namespace boost;wird der Namensraumboostin 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_traitsbeinhaltet. Diese Klasse ist vonstd::iterator_traitsabgeleitet 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 namespacenichts 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 Namensraumboostkeinen 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