Reputation: 133
I'm trying to use the stl copy () to print the key-value pair in a map. The code is as follows:
#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'm trying to overload operator<<. The problem is that the code won't compile unless I surround the definition of the overloaded operator<< with namespace std
. I think it is due to the name lookup mechanism of C++, which I still have trouble understanding. Even if I define non-template version like this:
ostream& operator<<(ostream& os, const pair<int,int>& p) {
return os << p.first << "\t" << p.second << endl;
}
It still won't compile. Can anyone explain why?
Upvotes: 3
Views: 175
Reputation: 55059
Your problem is with argument-dependent name lookup (ADL). The compiler is searching for an implementation of operator<<
in namespace std
, as both ostream
and pair
are in that namespace. You should 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 just use ostream_iterator<ostreamer<pair<const int, int>>>
instead of ostream_iterator<pair<int, int>>
. Note that because ostreamer
stores by reference and not by value, you can’t rely on the implicit conversion from pair<const int, int>
to pair<int, int>
anymore. You could change ostreamer
to store by value, but as it is, it has no overhead, and I think it’s better to be explicit anyway.
Upvotes: 2