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

2022-01-07 00:00:00 stream c++

以下代码不用多说:

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

推荐答案

问题是名称查找没有找到你的operator<<(ostream& os, const PAIR& r).尝试调用 operator<< 的代码位于 ostream_iterator<> 内的某处,它本身位于 std 命名空间内.名称查找在 ostream_iterator<>std 命名空间中寻找正确的函数;参数相关查找在这里没有帮助,因为这两个参数也都在 std 命名空间中.

The problem is that the name lookup does not find your operator<<(ostream& os, const PAIR& r). The code that tries to invoke the operator<< is in somewhere inside the ostream_iterator<> which is itself inside the std namespace. The name lookup looks around for the right function inside ostream_iterator<> and the std namespace; the argument dependent lookup does not help here because both of the parameters are in the std namespace, too.

所以,我的建议是 (1) 要么将您的运算符包装到 namespace std { } 中,但那是 UB、IIRC.或者 (2) 创建一个继承自 std::pair 的结构体以在您的命名空间中定义一个新类型,并使用 ADL 查找您的 operator<<().

So, my suggestion is (1) either to wrap your operator into namespace std { }, but that is UB, IIRC. Or (2) create a struct inheriting from std::pair to define a new type in your namespace, and using the ADL to find your operator<<().

更新:

我的第三个建议是使用自定义操纵器打印出该对.

My 3rd suggestion is to use a custom manipulator to print out the pair.

至于我的第二个建议,如果您可以使用 C++11,那么从 std::pair 继承应该很容易(未经测试):

As for my 2nd suggestion, if you can use C++11, inheriting from std::pair should be easy (untested):

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

如果您不能使用 C++11,那么我建议您使用自定义操纵器.

If you cannot use C++11, then I suggest using a custom manipulator.

相关文章