N3337,“工作草案,C++ 编程语言标准”,在第 13.3.1.2 节中给出了以下示例,p。10:
struct A { };
void operator + (A, A);
struct B {
void operator + (B);
void f ();
};
A a;
void B::f() {
operator+ (a,a); // error: global operator hidden by member
a + a; // OK: calls global operator+
}
但是,这只是一个注释:
注意:表达式中运算符的查找规则与函数调用中运算符函数名的查找规则不同,如下例所示:
我的问题是,标准中的什么地方说这是必须发生的事情,而不是仅仅用一个例子来说明?
据我所知,根据第 13.3.1.2 条,p。2、运算符表达式转换为运算符函数调用。那么为什么以及如何在上面的示例中有所不同呢?
编辑:
调查问题后,我认为我可能忽略了 p。3 和 p.6 在同一条款中共同声明,在查找运算符时,全局候选者和成员候选者被同等考虑(因此,如注释所述,查找规则不同)。但是,我对这个主题的调查是由这个例子引起的,它以与 GCC 4.8 和 Clang 相同的方式编译:
struct X {}; struct Y {};
void operator+(X, X) { }
void operator+(X, Y) { }
void test() {
void operator+(X, X);
X x; Y y;
x + x; // OK
x + y; // OK
operator+(x, y); // error
operator+(x, x); // OK
}
为什么直接调用操作符函数时块作用域声明会出现阴影,而通过运算符表达式调用时则没有?
以下是来自 GCC 的错误:
operators-main-ss.cpp: In function ‘void test()’:
operators-main-ss.cpp:13:17: error: could not convert ‘y’ from ‘Y’ to ‘X’
operator+(x, y); // error
^
这里来自 Clang:
operators-main-ss.cpp:13:16: error: no viable conversion from 'Y' to 'X'
operator+(x, y); // error
^
operators-main-ss.cpp:1:8: note: candidate constructor (the implicit copy constructor) not viable: no
known conversion from 'Y' to 'const X &' for 1st argument;
struct X {}; struct Y {};
^
operators-main-ss.cpp:7:22: note: passing argument to parameter here
void operator+(X, X);
^
编译器是否正确让块声明在一种情况下隐藏全局名称而不是另一种情况?