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