2016-10-12 26 views
-2

我已經重載operator<<map,pair(見下文),list。 他們很好地工作,是相當多才多藝。每當我需要更具體的東西時,我會定義其他優先的operator<<對於具有模板函數的迭代器,不能重載運算符<<對於多個模板化類,例如模板函數

但我無法對迭代器做同樣的事情。我得到編譯錯誤。我猜想處理operator<<的事實是無關緊要的,但重點在於使用迭代器進行模板化。

我做錯了什麼,或者我想做什麼是不可能的?

我現在的代碼(在Brian的回答之後)如下所示。請注意,在函數定義的每一行中都會簡要地指出錯誤,並在代碼的下面詳細說明。

#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*錯誤:

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*錯誤:

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) 
     ^
... 

舊代碼是(僅用於文檔目的):

#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; 
} 

回答

1

typename T::iteratorT是一個非推測範圍內,所以編譯器無法弄清楚什麼T應該是,當你嘗試調用operator<<一個迭代器類型。編寫了迭代工作過載

一種方法是使用SFINAE檢測給定類型是否是一個迭代與否:

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

請檢查更新的問題。 –

+0

@ sancho.s請發佈一個完整的,獨立的,最簡單的例子。刪除所有不需要的代碼來重現錯誤。 – Brian

+0

布賴恩,你是對的。完成。 –