不用说以下代码:
#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));
}
答案 0 :(得分:9)
这是一个常见问题:总之,在实例化operator<<
时,您看不到std::ostream_iterator
。
在实例化期间,名称查找尝试在命名空间operator<<
中查找std
。将找到候选者,因此不会考虑其他名称空间(特别是,不考虑全局名称空间)。然后,重载决策起作用:没有任何重载与参数类型匹配,因此编译失败。请注意,参数依赖查找在此处没有任何帮助,因为std::pair
也在名称空间std
中。
您有两种解决方案:
operator<<
包含在namespace std { }
中,但您应该知道这根据标准是非法的(17.4.3.1)std::copy
执行此任务并使用std::for_each
(使用'老式'仿函数或lambda)答案 1 :(得分:9)
问题是名称查找找不到您的operator<<(ostream& os, const PAIR& r)
。尝试调用operator<<
的代码位于ostream_iterator<>
内的某个位置,std
位于ostream_iterator<>
命名空间内。名称查找在std
和std
命名空间内查找正确的函数;参数依赖查找在这里没有帮助,因为这两个参数也都在namespace std { }
命名空间中。
所以,我的建议是(1)要么将你的运算符包装成std::pair
,那就是UB,IIRC。或者(2)创建一个继承自operator<<()
的结构,以在命名空间中定义新类型,并使用ADL查找std::pair
。
<强>更新强>
我的第三个建议是使用自定义操纵器打印出来。
至于我的第二个建议,如果你可以使用C ++ 11,继承struct PAIR : std::pair
{
using std::pair::pair;
};
应该很容易(未经测试):
{{1}}
如果您不能使用C ++ 11,那么我建议使用自定义操纵器。