3

我正在尝试使用 stl copy() 在地图中打印键值对。代码如下:

#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"));
} 

我正在尝试重载运算符<<。问题是代码不会编译,除非我将重载 operator<< 的定义用namespace std. 我认为这是由于 C++ 的名称查找机制,我仍然无法理解。即使我这样定义非模板版本:

ostream& operator<<(ostream& os, const pair<int,int>& p) {
    return os << p.first << "\t" << p.second << endl;
}

它仍然不会编译。谁能解释为什么?

4

1 回答 1

2

您的问题是与参数相关的名称查找(ADL)。编译器正在搜索operator<<in的实现namespace std,因为ostreampair都在该命名空间中。您应该制作一个operator<<从正确命名空间转发到的包装器:

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;
  }
};

然后只需使用ostream_iterator<ostreamer<pair<const int, int>>>而不是ostream_iterator<pair<int, int>>. 请注意,由于ostreamer按引用而非按值存储,因此您不能再依赖从pair<const int, int>to的隐式转换pair<int, int>。您可以更改ostreamer为按值存储,但实际上,它没有开销,而且我认为无论如何最好是明确的。

于 2013-02-19T02:47:32.030 回答