为什么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::pair
inheritance的结构来在你的命名空间中定义一个新types,并使用ADL来find你的operator<<()
。
更新:
我的第三个build议是使用自定义操纵器来打印出一对。
至于我的第二个build议,如果你可以使用C ++ 11,从std::pair
inheritance应该很容易(未经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)