Regras para pesquisa de operadores no C ++ 11
N3337, "Rascunho de trabalho, padrão para linguagem de programação C ++", fornece o seguinte exemplo na cláusula 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+
}
No entanto, esta é apenas uma nota:
Nota: As regras de consulta para operadores em expressões são diferentes das regras de pesquisa para nomes de função do operador em uma chamada de função, conforme mostrado no exemplo a seguir:
Minha pergunta é onde no padrão diz que isso é o que tem que acontecer ao invés de apenas ter a nota com um exemplo?
Tanto quanto eu posso dizer, de acordo com a cláusula 13.3.1.2, p. 2, as expressões do operador são convertidas em chamadas de função do operador. Então, por que e como deve haver uma diferença no exemplo acima?
Editar:Depois de analisar o problema, acho que posso ter negligenciado p. 3 e p.6 na mesma cláusula que, em conjunto, afirmam que candidatos globais e candidatos a membros são considerados igualmente ao procurar operadores (assim, as regras de pesquisa são diferentes, como diz a nota). No entanto, minha pesquisa sobre esse assunto foi originada por esse exemplo que compila da mesma maneira com o GCC 4.8 e o 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
}
Por que há sombreamento na declaração do escopo do bloco quando a função do operador é chamada diretamente, mas não quando é chamada pela expressão do operador?
Aqui estão os erros do 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
^
E aqui de 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);
^
Os compiladores estão corretos para que a declaração de bloco faça sombra ao nome global em um caso, mas não no outro?