Compilation error when overloading operator << with template arguments
I am trying to use stl copy () to print a key-value pair on a map. The code looks like this:
#include <iterator> #include <iostream> #include <algorithm> #include <map> using namespace std; //compile error if I comment out "namespace std" namespace std { template<typename F, typename S> ostream& operator<<(ostream& os, const pair<F,S>& p) { return os << p.first << "\t" << p.second << endl; } } int main() { map<int, int> m; fill_n(inserter(m, m.begin()), 10, make_pair(90,120)); copy(m.begin(), m.end(), ostream_iterator<pair<int,int> >(cout,"\n")); }
I am trying to overload operator <. The problem is that the code won't compile unless I surround the definition of the overloaded <c operator namespace std
. I think it has to do with the C ++ name lookup mechanism, which I still have a problem understanding. Even if I define a non-template version like:
ostream& operator<<(ostream& os, const pair<int,int>& p) { return os << p.first << "\t" << p.second << endl; }
It won't compile anyway. Can someone explain why?
source share
Your problem is name dependent lookup (ADL). The compiler looks for an implementation operator<<
in namespace std
, because both ostream
and pair
. You have to make a wrapper that forwards to operator<<
from the correct namespace:
template<class T> struct ostreamer { ostreamer(const T& value) : reference(value) {} const T& reference; friend ostream& operator<<(ostream& stream, const ostreamer& value) { return stream << value.reference; } };
Then use ostream_iterator<ostreamer<pair<const int, int>>>
instead ostream_iterator<pair<int, int>>
. Note that since it ostreamer
is stored by reference and not by value, you can no longer rely on implicit conversion from pair<const int, int>
to pair<int, int>
. You can change ostreamer
to store by value, but be that as it may, it has no overhead and I think its better to be explicit anyway.
source share