2
votes

I have created this template function:

// Output stream for container of type C
template<class C>
ostream& operator<<(ostream& os, const C& c) {
    os << "[";
    for (auto& i : c) {
        os << i;
        if (&i != &c.back()) os << ", ";
    }
    os << "]" << endl;
    return os;
}

but I have this error:

error: use of overloaded operator '<<' is ambiguous (with operand types 'std::ostream' (aka 'basic_ostream') and 'const char [2]')

The error is in the first line of the body of the function.

1
You really shouldn't provide unconstrained templates like that. You also shouldn't overload operators for types you don't own. If it were me, I would make a generic print or stringify function and use that to print/return a string able to be printed. - NathanOliver
You have provided a brief description of what happens what you compile the shown code: an error message. Your narrative ends at this point, and what seems to be missing from your narrative is an actual question. What is your specific question? - Sam Varshavchik
I noted that if v is a STL container I can't "cout << v" then I want an overload of operator<<. - asv

1 Answers

3
votes

This declaration

template<class C>
ostream& operator<<(ostream& os, const C& c)

is a match for any type. In particular, when you call inside that operator

os << "[";
os << i;
os << "]" << endl;

For all this calls your operator is a match in addition to the already existing output operators for strings and endl.

Don't provide operators for types you don't own. Instead you can write a

void print(const my_container&);

or use a tag to resolve ambiguity. For example you could use a

template <typename T>
struct pretty_printed_container {
    const T& container;
};

template <typename T>
pretty_printed_container<T> pretty_print(const T& t) { return {t};}

modify your output operator accordingly

template<class T>
std::ostream& operator<<(std::ostream& os, const pretty_printed_container<T>& c) {
    os << "[";
    for (const auto& i : c.container) {
        os << i;
        if (&i != &c.container.back()) os << ", ";
    }
    os << "]" << std::endl;
    return os;
}

And then use it like this

int main() {
    std::vector<int> x{1,2,3,4,5};
    std::cout << pretty_print(x);
}

Output:

[1, 2, 3, 4, 5]