C++ 重载函数名称查找错误

C++ Overloaded function name lookup error

本文关键字:查找 错误 重载 函数 C++      更新时间:2023-10-16

>我在C++中遇到了一个关于名称查找的奇怪错误。

可以使用以下最小示例重新创建错误:

#include <vector>
#include <iostream>
std::ostream& operator<<(std::ostream& out, const std::vector<int>& a) {
    for (size_t i = 0; i < a.size(); i++) {
        out << a[i] << std::endl;
    }
    return out;
}
namespace Test {
    struct A {
        // Label 1
        friend std::ostream& operator<<(std::ostream& out, const A&) {
            return out << "A" << std::endl;
        }
    };
    struct B {
        void printVector() noexcept {
            std::vector<int> v{1, 2, 3};
            std::cout << v << std::endl; // The error occurs in this line
        }
        // Label 2
        friend std::ostream& operator<<(std::ostream& out, const B&) {
            return out << "B" << std::endl;
        }
    };
}
int main() {
    Test::B().printVector();
}

编译这将导致以下错误消息:

cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'

您可以在此处亲自测试:http://cpp.sh/5oya

奇怪的部分是,如果您删除分别标有 // Label 1 // Label 2 的函数中的任何一个,代码可以编译并运行良好。

我现在的问题是:这是怎么回事?如何修复?

其他解决方法是在命名空间 std 中重载运算符<<,而不是在全局命名空间中。查找将在命名空间范围找到它)

namespace std
{
    std::ostream& operator<<(std::ostream& out, const std::vector<int>& a) {
        for (size_t i = 0; i < a.size(); i++) {
            out << a[i] << std::endl;
        }
        return out;
    }
}

在这里试试

[已编辑]

另一种解决方法,对于不想污染全局命名空间或std的清教徒来说,是

。将插入运算符与类位于同一命名空间中 它运作的。

。正如这里所讨论的。

namespace Test
{
    std::ostream& operator<<(std::ostream& out, const std::vector<int>& a) {
        for (size_t i = 0; i < a.size(); i++) {
            out << a[i] << std::endl;
        }
        return out;
    }
}

工作代码在这里。

您遇到了 ADL 问题,尽管我认为名称查找应该在全局命名空间中找到您的重载。(我没有具体的C++标准引号来知道编译器是否错误)。GCC(版本 6.3)和 Clang(版本 3.8.0)编译器发现重载,如下所示

一种解决方法是将全局运算符的name导入当前命名空间:

std::vector<int> v{1, 2, 3};
using ::operator <<; 
std::cout << v << std::endl;

如图所示:http://cpp.sh/95kuq

另一种解决方法是显式调用全局重载,如下所示:

std::vector<int> v{1, 2, 3};
::operator << (std::cout,  v); 
std::cout << std::endl;

如图所示: http://cpp.sh/4btyq