为什么ostream_iterator不能按预期工作?

不用多说下面的代码:

#include <utility> #include <vector> #include <iostream> #include <iterator> using namespace std; typedef pair<char, char> PAIR; ostream& operator <<(ostream& os, const PAIR& r) { return os << r.first; } int main() { vector<PAIR> coll; cout << coll[0]; // OK. // The following line will cause a compilation error! Why??? copy(coll.begin(), coll.end(), ostream_iterator<PAIR>(cout)); } 

问题是名称查找没有find你的operator<<(ostream& os, const PAIR& r) 。 试图调用operator<<的代码位于std命名空间内部的ostream_iterator<>内部。 名称查找将在ostream_iterator<>std名称空间中查找正确的函数; 依赖于参数的查找在这里没有帮助,因为这两个参数都在std名称空间中。

所以,我的build议是(1)或者把你的运算符封装到namespace std { } ,但这是UB,IIRC。 或者(2)创build一个从std::pairinheritance的结构来在你的命名空间中定义一个新types,并使用ADL来find你的operator<<()

更新:

我的第三个build议是使用自定义操纵器来打印出一对。

至于我的第二个build议,如果你可以使用C ++ 11,从std::pairinheritance应该很容易(未经testing):

 struct PAIR : std::pair { using std::pair::pair; }; 

如果你不能使用C ++ 11,那么我build议使用自定义的操纵器。

这是一个常见的问题: std::ostream_iterator当实例化std::ostream_iterator时,不会看到您的operator<<

在实例化过程中,名称查找尝试在命名空间std查找operator<< 。 候选人将被find,所以不会考虑其他命名空间(特别是不是全局命名空间)。 然后,重载parsing起作用:没有一个重载匹配参数types,所以编译失败。 请注意,依赖于参数的查找在这里没有任何帮助,因为std::pair也在命名空间std

你有两个解决scheme:

  • namespace std { }你的operator<< ,尽pipe你应该知道这是非法的 (17.4.3.1)
  • 避免使用std::copy来完成这个任务,并使用std::for_each (或者使用“老式”函数或者lambda)