2011-03-22 14 views
5

esto parece un poco hacia atrás para mí, pero funciona:¿Por qué el alcance del parámetro C++ afecta la búsqueda de funciones dentro de un espacio de nombres?

#include <iostream> 

namespace nTest 
{ 
    struct cTest {}; 

    void fTest(cTest& x) 
    { 
    std::cout << "nTest::fTest(cTest&) called" << std::endl; 
    } 
} 

int main(void) 
{ 
    nTest::cTest x; 
    fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest. 
    return 0; 
} 

Normalmente, se necesitaría NTest :: con el fin de acceder PRUEBA.F, pero su parámetro que pertenece a NTest parece añadir NTest a la lista de posibles ámbitos en los que buscar fTest. Me parece extraño que el alcance del parámetro influya en la búsqueda de funciones.

Esto compila bien en GCC, pero me pregunto si este uso es portátil. ¿Cuál es la definición oficial de este mecanismo de alcance?

+2

ADL - Argument Dependent Lookup (http://en.wikipedia.org/wiki/Argument-dependent_name_lookup) – Nim

+2

Lea también la respuesta aceptada [aquí] (http://stackoverflow.com/questions/2958648/what-are -the-pitfalls-of-adl) –

Respuesta

1

Originalmente fue diseñado para encontrar operadores sobrecargados, al igual que el operador < < que se utiliza para enviar una cadena std :: cout. Si no tuviéramos ADL, habría tenido que escribir su código así: std::operator<<(std::cout, "nTest::fTest(cTest&) called").

¡No demasiado bonito!

Y si funciona para los operadores, ¿por qué no funciona de la misma manera para las funciones?

12

Eso es ADL (Argument Dependent Lookup) o Koenig Lookup (para el diseñador de la característica). El objetivo de la función es que, en muchos casos, el mismo espacio de nombres contendrá tipos y funciones que se pueden aplicar a esos tipos, todos los cuales conforman el interface. Si ADL no estaba en su lugar, tendría que poner los identificadores en el alcance con las declaraciones using o tendría que calificar las llamadas.

Esto se convierte en una pesadilla ya que el lenguaje permite sobrecargas al operador. Consideremos el siguiente ejemplo:

namespace n { 
    struct test {}; 
    test operator+(test, test const &); // implemented 
}; 
int main() { 
    n::test a,b; 
    n::test c = a + b; //without ADL: c = n::operator+(a, b) 
} 

Si bien puede parecer una situación incómoda, consideran que n podría ser el std espacio de nombres, test podría ser ostream y operator+ podría ser operator<<:

int main(int argc, char**) { 
    std::cout << "Hi there, there are " << argc << " arguments" << std::endl; 
} 

Sin ADL , las llamadas a operator<< tendrían que ser explícitas, y además, debería saber cuál de ellas se implementa como una función gratuita versus un método. ¿Sabía que std::cout << "Hi" llama a una función gratuita y std::cout << 5 llama a una función miembro? No muchas personas se dan cuenta, y en serio, a casi nadie le importa. ADL lo esconde.

Cuestiones relacionadas