N3337,“C++编程语言标准”的工作草案,在第13.3.1.2条第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条款第2页的规定,操作符表达式会转换为操作符函数调用。那么为什么以及如何出现上述示例中的差异?
编辑:
经过研究,我认为可能已经忽略了相同条款中的第3页和第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);
^
编译器在一个情况下阻止声明块遮蔽全局名称,而在另一种情况下则没有。这样做是否正确?