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

时间:2017-01-12 19:23:34

标签: c++ operator-overloading name-lookup

我在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标记的任一函数,代码将编译并运行正常。

我现在的问题是:这里发生了什么?如何解决?

2 个答案:

答案 0 :(得分:0)

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

一种解决方法是将全局运算符的>>> lines = sc.textFile("README.md") # Create an RDD called lines >>> lines.count() # Count the number of items in this RDD 127 >>> lines.first() # First item in this RDD, i.e. first line of README.md u'# Apache Spark' 导入当前命名空间:

name

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

另一个解决方法是显式调用全局重载,如:

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

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

答案 1 :(得分:0)

其他解决方法是重载运算符&lt;&lt;在命名空间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;
    }
}

尝试Here

[EDITED]

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

  

...将插入操作符放在与类相同的命名空间中   它运作。

......正如here所述。

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

工作代码here