我在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
标记的任一函数,代码将编译并运行正常。
我现在的问题是:这里发生了什么?如何解决?
答案 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。