2011-02-03 15 views
22

Tengo un pequeño código aquí para su consideración que me desconcierta bastante. Lo extraño es que compila tanto en Sun Studio como en GCC aunque creo que no debería.Las funciones con argumentos de clase se filtran de un espacio de nombres?

Considera:

namespace name 
{ 
    class C 
    { 
     int a; 
    }; 

    void f(C c); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    name::C c; 

    name::f(c); 
    f(c); // <--- this compiles, strangely enough 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 

El argumento de clase desde el mismo espacio de nombres hace que la función f a 'fuga' fuera del espacio de nombres y ser accesibles sin name::.

¿Alguien tiene una explicación para esto? Sin duda, yo y no el compilador estamos equivocados aquí.

+0

Interesante, BTW intel compiler (icpc) compila esto también ... – Artyom

+0

Edité mi propia pregunta para eliminar los bits irrelevantes y facilitar la búsqueda para otros con el mismo problema. – lytenyn

Respuesta

28

Se llama argument-dependent lookup (o búsqueda Koenig). En resumen, el compilador buscará la función en los espacios de nombres que son los espacios de nombres de los tipos de argumentos.

+1

Gracias, esta es una característica de C++ que nunca había escuchado sobre ... – lytenyn

+5

@lytenyn: es una que usas todos los días :) :) std :: string s; s + = "aa"; ', here' + = 'proviene del espacio de nombres' std' aunque nunca lo haya especificado, gracias a ADL. –

+0

@ matthieu-m: tiene toda la razón, por supuesto, lo mismo cuando usa iostreams. Pero estas son las cosas pequeñas en las que nunca piensas a menos que alguien te meta la nariz :) Además, no recuerdo ningún libro de C++ que haya leído alguna vez, aunque es tan fundamental. Esto podría ser solo mi memoria, por supuesto. – lytenyn

11

Esto es Argument-Dependent Name Lookup, ak.a. ADL, a.k.a. Koenig búsqueda. Esto fue inventado para que los operadores de trabajo como se esperaba, por ejemplo:

namespace fu { 
    struct bar { int i; }; 
    inline std::ostream& operator<<(std::ostream& o, const bar& b) { 
     return o << "fu::bar " << b.i; 
    } 
} 

fu::bar b; 
b.i = 42; 
std::cout << b << std::endl; // works via ADL magic 

Sin ADL que tendría que llevar ya sea de forma explícita el operador de salida con using fu::operator<<; fea, o utilizar la llamada aún más feo explícita:

fu::operator<<(std::cout, b) << std::endl; 
+1

+1 para el enlace, ojalá hubieras resumido el artículo. – Crisfole

+2

El artículo es muy corto, ¿cuál es tu curiosidad? –

6

Se debe a la "búsqueda dependiente del argumento". Eliminar el const no cambiará el comportamiento que estás viendo. Para demostrar que es ADL, trate de mover el St estructura exterior del espacio de nombres ...

struct St 
{ 
    int a; 
}; 

namespace name 
{ 
    void f(const St& st); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    St st; 

    name::f(st); 
    f(st); // <--- now you will get the expected compile error 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 
1

que es causada por las operaciones de búsqueda depende argumento.

Cuestiones relacionadas