Rules for lookup of operators in C++11
c++, c++11
Solution
Are the compilers correct to have the block declaration shadow the global name in one case but not the other?
I have come to the conclusion that both compilers are wrong. I believe `x + y;` should also fail. 13.3.1.2p3 states it clearly:
The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored.
As a result, there should be no difference between `x + y;` and `operator+(x, y);` in your example. Commeau online produces the following errors with the code:
"ComeauTest.c", line 11: error: no operator "+" matches these operands
operand types are: X + Y
x + y; // OK
^
"ComeauTest.c", line 13: error: no suitable user-defined conversion from "Y"
to "X"
exists
operator+(x, y); // error
Problem
N3337, "Working Draft, Standard for Programming Language C++," gives the following example in clause 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+ } ``` However, this is just a note: Note: The lookup rules for operators in expressions are different than the lookup rules for operator function names in a function call, as shown in the following example: My question is where in the standard does it say that this is what has to happen as opposed to just having the note with an example? As far as I can tell, according to clause 13.3.1.2, p. 2, operator expressions are converted to operator function calls. So why and how should there be a difference in the example above? Edit: After looking into the problem, I think that I may have overlooked p. 3 and p.6 in the same clause that together state that global candidates and member candidates are considered equally when looking up operators (thus lookup rules are different as the note says). However, my inquiry into this subject was stemmed by this example that compiles in the same way with GCC 4.8 and 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 } ``` Why is there shadowing by the block scope declaration when the operator function is called directly but not when it is called by operator expression? Here are the errors from 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 ^ ``` And here from 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); ^ ``` Are the compilers correct to have the block declaration shadow the global name in one case but not the other?