Well, the code compiles and runs for me in clang++. Can't try with g++ on this computer.
Edit: Actually, it compiles with g++ as well, which makes sense because you only use the operator<<
in the main which is in the global namespace. I assume your actual code is different \Edit
But I'm familiar with the "ostream lvalue can't bind to ostream&&" error
How to explain. There is a problem in providing operator<<
between ostreams
and any std
class (like list
in your example, but I found it with vector
)
Mostly it works, but when the operator is called from a namespace (like your my
namespace) it breaks.
Why? Because "where do I look for this operator<< member"? See, there might be a lot of operator<< between ostreams and lists - each in a different namespace. So where does the compiler look for it?
It looks in the namespaces of each on its operands (in your case - both are from std
). And sometimes in the namespace of the caller (which in your case is my
).
I say "sometimes" because according to the standard it shouldn't, but g++ does it anyway. clang++ doesn't - but looks in the global namespace instead (hence why it worked for me)
Ideally, you'd want to put the operator<< inside the std
namespace (try it - it will work). BUT - that is against the standard. You are not allowed to do that. You can put it in the my
namespace and it should work find in g++, but not in other compilers.
It's a problem. I "solved" it by creating a wrapper - a class that exists in my own namespace and only holds a reference to the std
class - and can be printed.
template<class T> struct OutList<T>{
const std::list<T> &lst;
OutList(const std::list &l):lst(l){}
};
template<class T> OutList<T> outlist(const std::list<T> &lst){return OutList<T>(lst);}
std::ostream &operator<<(std::stream &out,const OutList<T> &lst){...}
....
std::cout << "list= "<<outlist(list)<<std::endl;
It isn't pretty, but that's all I found...