Alex Chudinov Alex Chudinov - 2 months ago 9
C++ Question

Printing std::vector of a user defined type

Please, look at the two code chunks below. In the second one I've just put the class A into a namespace. And now my mind boiled up trying to understand why the first one chunk is ok and the second one chunk is not.
Sorry, for a mostly code. Could you explain me why? I used Microsoft compiler C++14.
Please, help.

This is ok:

#include <iostream>
#include <vector>
#include <iterator>

class A;

class A{};

std::ostream & operator<<(std::ostream & out, const A & a)
{
out << "A";
return out;
}

int main()
{
std::vector<A> v({ A(), A(), A() });
//Prints: "A A A "
std::copy(v.begin(), v.end(), std::ostream_iterator<A>(std::cout, " "));
return 0;
}


This is not ok:

#include <iostream>
#include <vector>
#include <iterator>

namespace N { class A; }

class N::A{};

std::ostream & operator<<(std::ostream & out, const N::A & a)
{
out << "A";
return out;
}

int main()
{
std::vector<N::A> v({ N::A(), N::A(), N::A() });
//Compiler error C2679:
std::copy(v.begin(), v.end(),
std::ostream_iterator<N::A>(std::cout, " "));

//But this is still ok and prints "A A A" as intended.
//Please, uncomment and try:
/*
for (std::vector<N::A>::iterator it = v.begin(); it != v.end(); ++it)
std::cout << *it << " ";
*/

return 0;
}

Answer

The issue is std::copy can't find operator<<, without the help of ADL. It knows nothing about operator<< defined by you.

So you need to move operator<< into the same namespace where class A declared, to make ADL to take effect, then operator<< could be found.

namespace N { 
    class A; 
    std::ostream & operator<<(std::ostream & out, const A & a);
}

class N::A{};

std::ostream & N::operator<<(std::ostream & out, const N::A & a)
{
    out << "A";
    return out;
}

LIVE

Note for the first case, it works well, still because of ADL. Just the namesapce is global namespace (where class A and operator<< defined).