操作员<<过载分辨率 (C++)



下面的代码在a::b::print函数中给出了一个错误:Invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'Foo').

如果我注释掉命名空间b中的operator<<重载,错误就会消失。但我不明白为什么这会有所不同,因为它与 namspacea中的operator<<过载具有不同的签名。这是怎么回事?!

#include <iostream>
class Foo {};
namespace a {
std::ostream &operator<<(std::ostream &os, Foo &foo);
void print(Foo& foo) {
std::cout << foo;
}
namespace b {
std::ostream &operator<<(std::ostream &os, double d); // uncomment to resolve error
void print(Foo& foo) {
std::cout << foo; // error here
}
}
}

由于命名空间b嵌套在命名空间a内,因此在b中声明的名称将隐藏在a中声明的名称。 当名称查找发生在a::b::print中时,它会搜索b如果找不到要查找的内容,它会继续在a中搜索。 因此,它确实在b中找到运算符<<并停止查找,甚至不考虑a中正确的运算符。 当你注释掉它时,它会在b中找到它,并继续搜索a并找到它。 您可以通过在命名空间 b 中添加它来解决此问题:

using a::operator<<; 

但是,代码的真正问题是您没有正确使用 ADL(依赖于参数的查找)。 处理用户定义类型的运算符应与其操作的类型位于同一命名空间中。 ADL 的作用是添加额外的命名空间进行搜索,以便调用涉及的任何参数(或模板参数)都会自动考虑其命名空间。 (这就是为什么当您的代码在std之外时,可以将std命名空间中提供的运算符用于内置类型。

因此,operator<<移出命名空间a,并移入Foo所在的同一(全局)命名空间。 或者,可能更好的是,Foo移动到命名空间a

相关内容

  • 没有找到相关文章

最新更新