vector and ostream

Dave Dribin has a puzzler about being able to cout << vector << endl; at his web page. As I’ve been reading about this kind of stuff recently, I have a sample explanation and also, for fun, an explanation of why it’s impossible to do this correctly after the jump…

First of all, the obvious implementation:


#include
#include

template
std::ostream& operator< <(std::ostream& out, std::vector& vec)
{
string comma("");
out < < "vector<>: {";
for(std::vector::const_iterator it = vec.begin();
it != vec.end(); ++it)
{
out < < comma << *it;
if (comma.empty())
comma = ", ";
}
out << "};";
return out;
}

the comma thing is just me getting cutesy, but you get the idea.

However, here's the problem with this: This is actually ::operator< <(std::ostream&, std::vector&). And name resolution rules say two things: One, that if you use a function name with parameters in a namespace, the compiler should that namespace first for the function name even in the absense of a relevant using statement. Two, if any function with the same name (ignoring parameters) exists in that namespace, you do NOT need to check the global namespace.

That is std::foo(std::wstring); blocks ::foo(std::wstring). But std::foo(int i) ALSO blocks ::foo(std::string). For more information, see GotW #30.

One illegal fix: wrap it in namespace std { }. You can NEVER put something that's not part of the C++ standard API in namespace std. (See stdext::hash_map).

One potential fix: Put it in an anonymous namespace {} block. I need to find a language lawyer and see if that's valid and if that circumvents the namespace blocking rule above.

This entry was posted in tech. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>