c++ - español - lvalue required as left operand of assignment que significa
No se puede declarar un operador dentro de una función. Clang error o especificaciones? (2)
Es cierto que C permite que las funciones se declaren dentro de las funciones: 6.7.5.3 declaradores de función §17 (borrador n1256 para C99) dice (enfatice el mío)
Si la declaración se produce fuera de cualquier función, los identificadores tienen alcance de archivo y enlace externo. Si la declaración ocurre dentro de una función , los identificadores de las funciones f y fip tienen alcance de bloque y enlace interno o externo (dependiendo de qué declaraciones de alcance de archivo para estos identificadores son visibles), y el identificador del puntero pfi tiene alcance de bloque y sin vinculación
C ++ también los permite. El borrador n4296 para C ++ 14 dice:
13.2 Declaración coincidente [over.dcl]
...
2 Una función declarada localmente no está en el mismo ámbito que una función en un ámbito contenedor. [Ejemplo:
void f (const char *);
void g () {
vacío externo f (int);
...
(la cita anterior solo está aquí para tener una evidencia explícita de que C ++ permite declaraciones de funciones dentro de la función)
Incluso podría probar eso con su ejemplo esta línea:
bool op2 = operator == (x.value, y.value);
compila bien sin una sola advertencia y da los resultados esperados.
Así que diría que es un error en Clang.
Uno de los casos más raros de la esquina de C es que las funciones se pueden declarar dentro de otras funciones, por ejemplo,
void foo(void)
{
void bar(void); // Behaves as if this was written above void foo(void)
bar();
}
Esto se ha llevado a C ++, al menos para la mayoría de las funciones. Clang no parece reconocer el patrón si la función en cuestión pasa a llamarse operator ==.
struct foo
{
int value;
};
struct bar
{
foo value;
};
bool wot(const bar &x, const bar &y)
{
bool eq(const foo &, const foo &); // Declare function eq
bool operator==(const foo &, const foo &); // Declare function operator==
bool func = eq(x.value, y.value); // This line compiles fine
bool call = operator==(x.value, y.value); // Also OK - thanks user657267!
bool op = x.value == y.value; // This one doesn''t
return func && call && op;
}
bool test()
{
bar a;
bar b;
return wot(a,b);
}
GCC e ICC compilan esta multa. La comprobación de la manipulación de nombres en el objeto sugiere que el operador == ha sido declarado con los tipos correctos. Clang (probé hasta 3.8) errores:
error: invalid operands to binary expression
(''const foo'' and ''const foo'')
bool op = x.value == y.value;
~~~~~~~ ^ ~~~~~~~
A menos que la declaración se mueva directamente sobre la función, en cuyo caso Clang también está contento:
bool operator==(const foo &, const foo &);
bool wot(const bar &x, const bar &y)
{
return x.value == y.value; // fine
}
No puedo usar esta solución como el caso del "mundo real" que provocó que esta pregunta involucre capas de plantillas, lo que significa que solo conozco el nombre de tipo "foo" dentro de la declaración de función.
Creo que esto es un error en Clang: ¿existe un manejo especial de las funciones gratuitas de operatorX que prohíba declararlas dentro de una función?
Para operadores sobrecargados, vea [over.match.oper]/(3.2) :
[…] Para un operador binario
@
con un operando izquierdo de un tipo cuya versión cv-no calificada esT1
y un operando derecho de un tipo cuya versión cv-no calificada esT2
, [...] candidatos no miembros [...] se construyen como sigue:El conjunto de candidatos no miembros es el resultado de la búsqueda no calificada de
operator@
en el contexto de la expresión de acuerdo con las reglas habituales para la búsqueda de nombres en llamadas de función no calificadas (3.4.2), excepto que se ignoran todas las funciones miembro. Sin embargo, si ningún operando tiene un tipo de clase, […]
Es decir, tenemos exactamente las mismas reglas de búsqueda de nombres que en las llamadas normales, porque x.value
es de tipo de clase ( foo
). Es un error de Clang, y ocurre con todos los operadores binarios. Archivado como #27027 .