Kollision von << für Vector mit Boost::Variant
-
Hallo,
ich habe einen Ausgabe-Operator für Vector geschrieben
template<class T> std::ostream& operator<<(std::ostream& s, const std::vector<T>& v) { for (typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); ++it) s << *it << " "; return s; }der sich im Namespace
IObefindet.In einem meiner Source-Dateien kommt es nun bei Verwendung des Operators zu einer Kollision mit dem, was is Boost::Variant definiert ist. So führt
vector<unsigned> s = IO::size(LSPs); cout << s << endl; IO::operator<<(cout, s) << endl;zur Fehlermeldung
../src/node/rev/nd_creation.cpp: In member function ‘void Node::Prob_Nd::set_anc_LSPs(boost::multi_array<gsl_matrix*, 2ul, std::allocator<gsl_matrix*> >)’: ../src/node/rev/nd_creation.cpp:99: error: no match for ‘operator<<’ in ‘std::cout << s’ /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:108: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:117: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:127: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:165: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/ostream.tcc:91: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:180: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/ostream.tcc:105: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:191: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:200: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:209: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:221: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/ostream:225: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/ostream.tcc:119: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>] /home/atlas12/ingo/workspace/Gen_Recon/src/node/alphabet.h:40: note: std::ostream& Node::operator<<(std::ostream&, const Node::Alphabet&) ../src/node/rev/rev_nd.h:150: note: std::ostream& Node::operator<<(std::ostream&, const Node::Rev_Nd&) make: *** [src/node/rev/nd_creation.o] Error 1bezüglich der zweiten Zeile, während die dritte fehlerlos kompiliert wird.
Daher die Frage: Muss ich da einen Workaround wie in der dritten Zeile machen oder gibt es da bessere Alternativen? Kein
using namespace boost;zu verwenden würde in diesem Fall zu aufwendig sein.
-
template<class T> std::ostream& operator<<(std::ostream& s, const std::vector<T>& v) { for (typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); ++it) s << *it << " "; return s; }
template<class T> std::ostream& operator<<(std::ostream& s, const std::vector<T>& v) { std::copy( std::begin(v), std::end(v), std::ostream_iterator<T>{s, " "} ); return s; }Es dürfte doch offensichtlich sein, dass ADL nicht im Namensraum IO nachsieht. Also entweder machst du den bekannt, oder du rufst explizit die Operatorfunktion auf.
Oder du überlädst den Operator außerhalb von IO. Wobei das ja irgendein Problem zu verursachen scheint.
-
Moment mal, was hat Boost.Variant mit
std::vectorzu tun?In einem meiner Source-Dateien kommt es nun bei Verwendung des Operators zu einer Kollision mit dem, was is Boost::Variant definiert ist.
Wieso sollte Boost.Variant den Ausgabeoperator für
vectordefinieren?
-
- schrieb:
template<class T> std::ostream& operator<<(std::ostream& s, const std::vector<T>& v) { for (typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); ++it) s << *it << " "; return s; }
template<class T> std::ostream& operator<<(std::ostream& s, const std::vector<T>& v) { std::copy( std::begin(v), std::end(v), std::ostream_iterator<T>{s, " "} ); return s; }irrelevant. Und bitte ändere den Namen. * ist nicht höflich.
-
in der Fehlermeldung kommt boost nicht einmal vor.
-
Und bitte ändere den Namen. * ist nicht höflich.
Leute, die Email an Markus ist schon laengst verschickt! Vor Tagen!
irrelevant.
War ein Tipp wie man es direkter schreiben kann, ohne eine ellenlange
for-Schleife mitconst_iteratoren.
Edit: Das war natuerlich fuer C++03, ich habe es aus Versehen mit C++11 gemixt...
In C++11 wuerde man direct zu einer huebschen Schleife tendieren:for( auto const& e : v ) std::cout << e << ' ';otze schrieb:
in der Fehlermeldung kommt boost nicht einmal vor.
Eben.
Was hat Boost damit zu tun.
-
ingobulla schrieb:
Hallo,
ich habe ein[ Problem]Hallo ingobulla. Es sieht so aus, als sei das ein Problem, bei dem du noch etwas zum Thema
Namensauflösung zu lernen hast. Leider hast du kein vollständiges Minimalbeispiel
gepostet. Bitte versuch dein Problem auf ein vollständiges Minimalbeispiel zu reduzieren.
Z.B. so etwas:namespace s { struct vec {}; } namespace io { void func(s::vec&); } namespace test { void func(int&); void test() { using namespace io; s::vec v = {}; func(v); // findet trotz using-Direktive mein io::func nicht :-( } } // namespace test int main() { test::test(); }Deine Code-Fragmente sind weit von einem vollständigen Beispiel entfernt, dass man da
eigentlich fast nichts zu sagen kann.Ergänzung:
Sehr wahrscheinlich hast du hier ein "name hiding" Problem. Deinoperator<<kann
nicht per ADL (argument dependent lookup) gefunden werden, weil er gar nicht in einem
dem std::vector assoziierten Namensraum (std) deklariert wurde. Eine using-Direktive,
alsousing namespace IO;kann dir hier nur bedingt helfen, weil die Namenssuche
schon vorher abbrechen kann, bevor der Namensraum IO untersucht wird. Das siehst du auch
in meinem Beispiel. Bevor io durchsucht wird, findet der Compiler test::func und hört
mit der "normalen" Namenssuche auf. ADL kommt dann zum Einsatz. aber ADL durchsucht hier
nur noch den Namensraums. Und da gibt's keinfunc.In meinem Beispiel kann man jetzt die using-Direktive durch eine using-Deklaration ersetzen:
using io::func;. Allerdings ist das keine Lösung für boost::variant. boost::variant
weiß nicht, dass zum vector der passende operator<< im Namensraum IO ist. Du benutzt also
entweder für die Ausgabe einen eigenen Visitor oder wrappst den Vektor in einer eigenen
Klassetemplate<class T> class myvec { std::vector<T> vec_; ::: };wobei operator<< in demselben Namensraum deklariert werden muss, damit er per ADL gefunden
werden kann.
-
Bevor io durchsucht wird, findet der Compiler test::func und hört mit der "normalen" Namenssuche auf.
Und wieso wird io erst nach test durchsucht, obwohl wir doch die using-
DeklarationDirektive direkt in der Funktion stehen haben?
Weil:A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive.
During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.Das heißt, func wird vom Namelookup als ein Member des globalen Namensraums behandelt - und es wird ja schließlich zuerst in den innersten und erst dann in den äußeren Scopes gesucht.
-
Arcoth schrieb:
Bevor io durchsucht wird, findet der Compiler test::func und hört mit der "normalen" Namenssuche auf.
Und wieso wird io erst nach test durchsucht, obwohl wir doch die using-Deklaration direkt in der Funktion stehen haben?
Du meintest sicherlich "using-Direktive".
Anyhow, danke für's Raussuchen und Zitieren.
-
Ups, da habe ich mich verschrieben.
using-Deklaration wäre natürlich etwas a lausing io::func;Und das ist gerade, was ja funktioniert.