c++ - resueltos - ¿Cuál es el nombre completo de una función de amigo definida dentro de una clase?
que es un objeto en programacion (2)
¿Cuál es el nombre completo de una función de amigo definida dentro de una clase?
Recientemente vi un ejemplo análogo al siguiente. ¿Cuál es el nombre completo de val()
continuación?
#include <iostream>
namespace foo {
class A {
int x;
public:
A(int x = 0) : x(x) { }
friend int val(const A &a) { return a.x; }
};
}
int main() {
foo::A a(42);
// val() found using ADL:
std::cout << val(a) << std::endl;
// foo::val(a); // error: ''val'' is not a member of ''foo''
// foo::A::val(a); // error: ''val'' is not a member of ''foo::A''
return 0;
}
¿Es la búsqueda dependiente del argumento la única forma en que se puede encontrar val()
?
Es cierto que esto no se deriva de un problema práctico. Simplemente estoy buscando para obtener una mejor comprensión.
¿Es la búsqueda dependiente del argumento la única forma en que se puede encontrar val ()?
Sí, es la única manera. Para citar la norma sagrada en [namespace.memdef]/3 :
Si una declaración de amigo en una clase no local declara por primera vez una clase, función, plantilla de clase o plantilla de función, el amigo es miembro del espacio de nombres que lo contiene más íntimamente. La declaración de amigo no hace que el nombre sea visible para una búsqueda no calificada o una búsqueda calificada.
Entonces, mientras que val
es miembro de foo
, no se puede ver solo desde la declaración de amigos. Se requiere una definición fuera de clase (que también es una declaración) para hacerla visible. Para una definición en línea (y ninguna declaración fuera de clase) significa que ADL es la única forma de llamar a la función.
Como un bono adicional, C ++ una vez tuvo un concepto de "inyección de nombre de amigo". Sin embargo, eso se eliminó y las reglas para ADL se ajustaron como reemplazo. Se puede encontrar una descripción más detallada en el documento N0777 (pdf).
Estándar de C ++ [7.3.1.2/3 (de ISO / IEC 14882: 2011)]:
Cada nombre declarado primero en un espacio de nombres es un miembro de ese espacio de nombres. Si una declaración de amigo en una clase no local declara por primera vez una clase o función, la clase o función amiga es un miembro del espacio de nombres más interno. El nombre del amigo no se encuentra por búsqueda no calificada (3.4.1) o por búsqueda calificada (3.4.3) hasta que se proporcione una declaración coincidente en ese ámbito de espacio de nombres (ya sea antes o después de la definición de clase que otorga amistad) . Si se llama a una función amiga, su nombre se puede encontrar por la búsqueda de nombres que considera las funciones de los espacios de nombres y las clases asociadas con los tipos de los argumentos de la función (3.4.2). Si el nombre en una declaración de amigo no está calificado ni es una plantilla-id y la declaración es una función o un especificador de tipo elaborado, la búsqueda para determinar si la entidad ha sido declarada previamente no considerará ningún ámbito fuera del espacio de nombres más interno. .