1
votes

By means of a template, I overloaded operator<< so that it outputs all the elements of a container:

template<typename T, template<typename> typename C>
ostream& operator<<(ostream& o, const C<T>& con) { for (const T& e : con) o << e; return o; }

It works OK with std::vectors, but it produces an error message when I attempt to apply it to a std::list:

error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘std::__cxx11::list’) cout << li;

Here's is my code excerpt (compiled on GCC 5.2.1, Ubuntu 15.10):

#include "../Qualquer/std_lib_facilities.h"

struct Item {

    string name;
    int id;
    double value;

    Item(){};
    Item(string n, int i, double v):
        name{n}, id{i}, value{v} {}
};

istream& operator>>(istream& is, Item& i) { return is >> i.name >> i.id >> i.value; }
ostream& operator<<(ostream& o, const Item& it) { return o << it.name << '\t' << it.id << '\t' << it.value << '\n'; }

template<typename T, template<typename> typename C>
ostream& operator<<(ostream& o, const C<T>& con) { for (const T& e : con) o << e; return o; }


int main()
{
    ifstream inp {"../Qualquer/items.txt"};
    if(!inp) error("No connection to the items.txt file\n");

    istream_iterator<Item> ii {inp};
    istream_iterator<Item> end;
    vector<Item>vi {ii, end};
    //cout << vi;//this works OK
    list<Item>li {ii, end};
    cout << li;//this causes the error
}

However, when I write a template specifically for the std::list, it works OK:

template<typename T> 
ostream& operator<<(ostream& o, const list<T>& con) { for (auto first = con.begin(); first != con.end(); ++first) o << *first; return o; }

Why does the ostream& operator<<(ostream& o, const C<T>& con) template turns out to be inapplicable to std::list?

1
as far as I can see your template operator takes containers that takes only one template parameter template<typename> typename C as such both std::vector and std::list shouldn't match - W.F.
This is Bjarne's teaching header, right? He has a template <class T> class Vector and a #define vector Vector. @W.F. - T.C.
@T.C. Yes, the header file is Bjarne's teaching header from his site. - Jarisleif

1 Answers

2
votes
template<typename T, template<typename> typename C>
ostream& operator<<(ostream& o, const C<T>& con) { for (const T& e : con) o << e; return o; }

Why so complicated? You need type name T only to use it in your for loop. You may as well get it through C::value_type or just use auto keyword:

template<typename C>
ostream& operator<<(ostream& o, const C& con)
{
    for (const typename C::value_type& e : con) o << e; return o;
}

template<typename C>
ostream& operator<<(ostream& o, const C& con)
{
    for (auto& e : con) o << e; return o;
}