2016-10-12 4 views
-2

Ich habe operator<< für mehrere Vorlagenklassen, z. map, pair (siehe unten), list. Sie arbeiten gut und sind sehr vielseitig. Wann immer ich etwas spezifischeres brauche, definiere ich andere operator<<, die Vorrang haben.Kann den Operator << für einen Iterator mit einer Template-Funktion nicht überladen

Aber ich konnte nicht das gleiche für Iteratoren tun. Ich bekomme Kompilierfehler. Ich denke, die Tatsache, dass wir uns mit operator<< beschäftigen, ist irrelevant, aber der Punkt ist ein Templating mit Iteratoren.

Mache ich etwas falsch, oder was ich tun möchte, ist nicht möglich?

Der Code, den ich jetzt (nach der Antwort von Brian) habe, ist unten gezeigt. Beachten Sie, dass die Fehler in jeder Zeile in der Definition der Funktion kurz und genauer unterhalb des Codes kurz notiert werden.

#include <iostream> 
#include <map> 
#include <string> 
using namespace std; 

typedef pair<string, char> pair_t; 
typedef map<pair_t::first_type, pair_t::second_type> map_t; 
typedef pair<map_t::iterator, bool> retval_insert_t; 

// Templated form of overloading << for a pair 
template<typename first_class, class second_class> 
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p); 
// Templated form of overloading << for an iterator ... does not work 
template <class T, class = typename iterator_traits<T>::value_type> 
ostream& operator<<(ostream& os, T iterator); 

int main(void) { 
    pair_t p2; 
    p2 = make_pair(string("Fer"), 'C'); 

    map_t grade_list; 
    retval_insert_t retval = grade_list.insert(p2); 
    cout << retval.first << endl; // Does not work with a templated << 

    return 0; 
} 

//********************** Overloaded << functions *************************************** 

// ***** pair 
// Templated form of overloading << for a pair 
template<class first_class, class second_class> 
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p) 
{ 
    os << "(" << p.first << ", " << p.second << ")"; // Compilation error: Ambiguous overload for the first << 
    return os; 
} 

template <class T, class = typename iterator_traits<T>::value_type> 
ostream& operator<<(ostream& os, T iterator) 
{ 
    os << iterator; // No compilation error, but segmentation fault 
    os << *iterator; // Compilation error if uncommenting: Cannot bind 
    //cout << "Testing" << endl; // Compilation error if uncommenting: Ambiguous overload for the first << 
    cout << 1 << endl; 
    return os; 
} 

*Cannot bind* Fehler:

g++ -Wall -Wunused -Wuninitialized -Wextra -std=gnu++11 -g -g3 -std=gnu++11 -c -o test_iters.o test_iters.cpp 
test_iters.cpp: In instantiation of ‘std::ostream& operator<<(std::ostream&, T) [with T = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, char> >; <template-parameter-1-2> = std::pair<const std::basic_string<char>, char>; std::ostream = std::basic_ostream<char>]’: 
test_iters.cpp:20:17: required from here 
test_iters.cpp:31:8: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’ 
    os << *iterator; // Compilation error if uncommenting: Cannot bind 
     ^
In file included from /usr/include/c++/4.8/iostream:39:0, 
       from test_iters.cpp:1: 
/usr/include/c++/4.8/ostream:602:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = std::pair<const std::basic_string<char>, char>]’ 
    operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) 
    ^
make: *** [test_iters.o] Error 1 

*Ambiguous override* Fehler:

g++ -Wall -Wunused -Wuninitialized -Wextra -std=gnu++11 -g -g3 -std=gnu++11 -c -o test_iters.o test_iters.cpp 
test_iters.cpp: In function ‘std::ostream& operator<<(std::ostream&, T)’: 
test_iters.cpp:32:7: error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const char [8]’) 
    cout << "Testing" << endl; // Compilation error if uncommenting: Ambiguous overload for the first << 
    ^
test_iters.cpp:32:7: note: candidates are: 
In file included from /usr/include/c++/4.8/iostream:39:0, 
       from test_iters.cpp:1: 
/usr/include/c++/4.8/ostream:174:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
     operator<<(bool __n) 
    ^
/usr/include/c++/4.8/ostream:245:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
     operator<<(const void* __p) 
    ^
test_iters.cpp:28:10: note: std::ostream& operator<<(std::ostream&, T) [with T = const char*; <template-parameter-1-2> = char; std::ostream = std::basic_ostream<char>] 
ostream& operator<<(ostream& os, T iterator) 
     ^
... 

Old Code ist (nur für Dokumentationszwecke):

#include <iostream> 
#include <map> 
#include <list> 
#include <string> 
using namespace std; 

typedef pair<string, char> pair_t; 
typedef map<pair_t::first_type, pair_t::second_type> map_t; 
typedef pair<map_t::iterator, bool> retval_insert_t; 

// ***** pair 
// Templated form of overloading << for a pair 
template<typename first_class, class second_class> 
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p); 
// ***** iterator 
// Templated form of overloading << for a const_iterator 
template<class T> 
ostream& operator<<(ostream& os, typename T::const_iterator it); 
// Templated form of overloading << for an iterator ... does not work 
template<class T> 
ostream& operator<<(ostream& os, typename T::iterator it); 
// Explicit form of overloading << for an iterator 
ostream& operator<<(ostream& os, map_t::iterator it); // Compile error if commenting this line 
// ***** return value of insert (a map) 
// Explicit form of overloading << for the return value of insert 
ostream& operator<<(ostream& os, const retval_insert_t& retval); 


int main(void) { 
    pair_t p2; 
    p2 = make_pair(string("Fer"), 'C'); 

    map_t grade_list; 
    retval_insert_t retval = grade_list.insert(p2); 
    cout << retval.first << endl; // Does not work with a templated operator<< 

    return 0; 
} 

//********************** Overloaded << functions *************************************** 
//************************ Explicit and templated **************************************** 

// ***** pair 
// Templated form of overloading << for a pair 
template<class first_class, class second_class> 
ostream& operator<<(ostream& os, const pair<first_class, second_class>& p) 
{ 
    os << "(" << p.first << ", " << p.second << ")"; 
    return os; 
} 

// ***** iterator 
// Templated form of overloading << for a const_iterator 
template<class T> 
ostream& operator<<(ostream& os, typename T::const_iterator it) 
{ 
    os << *it; 
    return os; 
} 
// Templated form of overloading << for an iterator ... does not work 
template<class T> 
ostream& operator<<(ostream& os, typename T::iterator it) 
{ 
    os << *it; 
    return os; 
} 
// Explicit form of overloading << for an iterator 
ostream& operator<<(ostream& os, map_t::iterator it) 
{ 
    os << *it; 
    return os; 
} 

// ***** return value of insert (a map) 
// Explicit form of overloading << for the return value of insert 
ostream& operator<<(ostream& os, const retval_insert_t& retval) 
{ 
    os << "retval : <" << retval.first << ", " << retval.second << ">"; 
    return os; 
} 

Antwort

1

Die T in typename T::iterator ist ein nicht-abgeleitete Kontext, so dass der Compiler nicht herausfinden können, was T sein soll, wenn Sie versuchen operator<< für einen Iteratortyp aufzurufen.

Eine Möglichkeit, eine Überlastung des Schreibens, die für Iteratoren arbeitet SFINAE verwendet, um festzustellen, ob eine bestimmte Art ein Iterator ist oder nicht:

template <class T, class = typename std::iterator_traits<T>::value_type> 
std::ostream& operator<<(std::ostream& os, T iterator); 
//          ^This T can be deduced 
+0

Bitte aktualisierte Frage prüfen. –

+0

@ sancho.s Bitte posten Sie ein komplettes, eigenständiges, minimales Beispiel. Entfernen Sie den gesamten Code, der zur Reproduktion des Fehlers nicht erforderlich ist. – Brian

+0

Brian, Sie haben Recht. Erledigt. –

Verwandte Themen