c++ - vector<int> 的 ostream_iterator 无法编译。为什么?

标签 c++ vector iterator ostream

请参阅以下最小可重现示例:

#include <iostream>
#include <vector>
#include <algorithm>

// Define inserter operator for std::vector<int>
std::ostream& operator << (std::ostream& os, const std::vector<int>& v) {
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(os, " "));
    return os;
}
// Define inserter operator for std::vector<std::vector<int>>
std::ostream& operator << (std::ostream& os, const std::vector<std::vector<int>>& vv) {
    
    // ******* Error in this line *****
    std::copy(vv.begin(), vv.end(), std::ostream_iterator<std::vector<int>>(os,"\n"));

    // OK. The following works and will call the operator above
    for (const std::vector<int>& v : vv) os << v << '\n';
    return os;
}
int main() {
    std::vector<std::vector<int>> vvi{ {1,2}, {3,4,5}, {6,7,8,9 } };
    std::cout << vvi;
    return 0;
}

std::ostream_iterator<std::vector<int>>无法编译,编译器说:

binary '<<': no operator found which takes a right-hand operand of type 'const _Ty' (or there is no acceptable conversion)

虽然 std::vector<int> 的插入操作符可用。

如果我改用:

for (const std::vector<int>& v : vv) os << v << '\n';

std::vector<int> 的插入运算符将被调用。但在 std::ostream_iterator 的情况下则不然。 .

CppReference 对我没有帮助。

为什么不能编译?

最佳答案

第一个问题是你缺少一个

#include <iterator>

您表明您已经熟悉 cppreference.com,因此您应该注意 std::ostream_iterator被指出需要此头文件。

但编译失败的真正原因是std::copy调用了重载运算符。这自然是在 std 中命名空间。由于调用 << 的代码运算符位于 std命名空间,重载解析搜索 std << 定义的重载的命名空间,并找到一大堆针对各种本地类型的数据。所有这些重载决议都会失败。它们都不适合 std::vector<int>不会搜索全局命名空间来查找您的自定义 <<过载,因为至少有一个<<过载可在 std 中找到命名空间。游戏结束。

如果没有定义<< std 中的重载命名空间,然后重载解析最终会找到您的自定义重载。唉,事实并非如此。

消除编译错误的一种方法是将重载放入 std 中。命名空间:

namespace std {
    // Define inserter operator for std::vector<int>
    std::ostream& operator << (std::ostream& os, const std::vector<int>& v) {
        std::copy(v.begin(), v.end(), std::ostream_iterator<int>(os, " "));
        return os;
    }
}

但是,this is pedantic undefined behavior 。无论如何,这就是编译错误的原因: << 的现有重载。在 std 中搜索命名空间优先,因为它们是从 std::copy 内部调用的,并且首先找到现有的重载解析,因此不考虑其他命名空间中的其他潜在重载。

关于c++ - vector<int> 的 ostream_iterator 无法编译。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65539637/

相关文章:

algorithm - 如何计算一个点到矩形最近点的距离?

c++ - 移动 vector 是否会使迭代器无效?

Java 遍历集合

c++ - 数据成员是否形成范围?

c++ - C++ 对 int 的读写是原子的吗?

c++ - 有没有办法根据用户的输入访问类对象的信息?

c++ - 使用 C++ 原子库,我应该使用什么内存顺序进行加载,然后进行比较交换?

c++ - 声明和定义结构有什么区别?

c++ - std::vector: vec.data() 或 &vec[0]

c++ - 创建分类音乐库的有效方法