C++ 找不到全局命名空间中定义的运算符

C++ 找不到全局命名空间中定义的运算符,c++,C++,考虑以下示例: namespace X { struct A { static const A aaa; }; const A A::aaa = {}; } bool operator == (const X::A &a, const X::A &b) { return true; } bool workaround (const X::A &a, const X::A &b) { return a == b; } namespace Y {

考虑以下示例:

namespace X {
    struct A { static const A aaa; };
    const A A::aaa = {};
}

bool operator == (const X::A &a, const X::A &b) { return true; }
bool workaround (const X::A &a, const X::A &b) { return a == b; }

namespace Y {
    using X::A;

    struct B { const A & an_a() const { static A a; return a; } };

    bool operator == (const B &a, const B &b) { return true; }

    bool foo (const B &b) {
        return b.an_a() == A::aaa;
        //return workaround(b.an_a(), A::aaa);
    }
}

int main () {}
此代码无法编译
foo
,因为
=
运算符解析命名空间
Y
中的一个,而不是全局命名空间中的一个


我想我理解这是因为C++定义了ADL的方式,如果该类属于命名空间,它似乎明确排除了搜索全局命名空间。但是,对我来说,这似乎仍然违反直觉。是否有解释说明为什么全局名称空间不能包含在要搜索的名称空间集中

操作符==

为了一致性,操作符被认为只是函数名,函数在封闭范围内隐藏任何名称(即使参数类型不同)。(后一条规则可能是为了防止在不同范围内声明的函数之间发生意外的重载解析交互)

您的
::operator==(const X::A&,const X::A&)
Y::operator==(const B&,const B&)
隐藏(在
Y
中),并且它不被认为是
X::A
接口的一部分(因为它不在直接命名空间
X
中),因此您无法找到它


如果您愿意更改比较的拼写,可以使用难看的显式
::operator==(b.an_a(),a::aaa)
而不是添加
变通方法

不是重复,而是一些解释:我认为这意味着由于
a
未在全局命名空间中声明,不考虑全局命名空间中的运算符
foo
是名称空间
Y
的一部分,它将两个
A
对象从名称空间
X
传递到
操作符==
,因此编译器将只在名称空间
Y
X
中查找匹配的操作符,而没有找到。也可以在cppreference.com上查看ADL使用的更全面的规则列表;一旦它找到那个名字,它就停止了。在您的示例中,它查找
Y::operator==
,并停止在那里,不查看任何封闭范围。ADL只查看与参数关联的名称空间——在您的例子中,
X
;它根本不会进入封闭范围。名称查找总是在找到名称后停止,而不管重载解析是否会成功。这不是ADL特有的。我想你得问问柯尼格。我不能证明他的精神状态。
.code.tio.cpp:17:25: error: invalid operands to binary expression ('const X::A' and 'const X::A')
    return b.an_a() == A::aaa;
           ~~~~~~~~ ^  ~~~~~~
.code.tio.cpp:14:10: note: candidate function not viable: no known conversion from 'const X::A' to 'const Y::B' for 1st argument
    bool operator == (const B &a, const B &b) { return true; }
     ^
1 error generated.