¿Cuáles son algunas buenas explicaciones sobre lo que el argumento de la búsqueda dependiente es? Muchas personas también llaman Búsqueda de Koenig así.

Preferiblemente me gustaría saber:

  • ¿Por qué es una buena cosa?
  • ¿Por qué es una mala cosa?
  • ¿Cómo funciona?

OriginalEl autor user965369 | 2011-11-13

4 Comentarios

  1. 183

    Búsqueda de Koenig, o El Argumento De La Búsqueda Dependiente De, describe cómo los nombres incompletos son considerados por el compilador de C++.

    El C++11 estándar § 3.4.2/1 estados:

    Cuando el postfix-expresión en una llamada de función (5.2.2) es un incompetente-id, otros espacios de nombres no se consideran durante la habitual incondicional de búsqueda (3.4.1) se pueden buscar, y en esos espacios de nombres los espacios de nombres ámbito amigo declaraciones de función (11.3) de otra manera no visible puede ser encontrado. Estas modificaciones a la búsqueda dependen de los tipos de los argumentos (y para la plantilla plantilla argumentos, el espacio de nombres de la plantilla
    argumento).

    En términos más simples Nicolai Josuttis estados1:

    Usted no tiene que calificar el espacio de nombres de funciones si uno o más tipos de argumentos se definen en el espacio de nombres de la función.

    Un sencillo ejemplo de código:

    namespace MyNamespace
    {
        class MyClass {};
        void doSomething(MyClass);
    }
    
    MyNamespace::MyClass obj; //global object
    
    
    int main()
    {
        doSomething(obj); //Works Fine - MyNamespace::doSomething() is called.
    }

    En el ejemplo de arriba no hay ni un using-declaración ni un using-directiva, pero todavía el compilador identifica correctamente el nombre no calificado doSomething() como la función declarada en el espacio de nombres MyNamespace mediante la aplicación de búsqueda de Koenig.

    ¿Cómo funciona?

    El algoritmo indica al compilador que no basta con mirar en el ámbito local, sino también el espacio de nombres que contiene el argumento del tipo. Así, en el código anterior, el compilador encuentra que el objeto obj, que es el argumento de la función doSomething(), pertenece al espacio de nombres MyNamespace. Así, se ve en ese espacio de nombres para buscar la declaración de doSomething().

    ¿Cuál es la ventaja de búsqueda de Koenig?

    Simples como el código de ejemplo anterior se muestra arriba, la búsqueda de Koenig proporciona comodidad y facilidad de uso para el programador. Sin búsqueda de Koenig no sería una sobrecarga en el programador, para especificar repetidamente los nombres completos, o en su lugar, el uso de numerosas using-declaraciones.

    Por qué la crítica a la búsqueda de Koenig?

    La excesiva dependencia de la búsqueda de Koenig puede conducir a la semántica de los problemas, y coger el programador de apagado de la guardia, a veces.

    Considere el ejemplo de std::swap, que es un estándar de la biblioteca de algoritmo para intercambiar dos valores. Con la búsqueda de Koenig, habría que ser cauteloso mientras que el uso de este algoritmo porque:

    std::swap(obj1,obj2);

    no puede mostrar el mismo comportamiento como:

    using std::swap;
    swap(obj1, obj2);

    Con la ADL, que versión de swap función se llama dependerá del espacio de nombres de los argumentos que se le pasan.

    Si existe un espacio de nombres A y si A::obj1, A::obj2 & A::swap() existe, entonces el segundo ejemplo, el resultado será una llamada a A::swap(), que podría no ser lo que el usuario quería.

    Además, si por alguna razón ambos A::swap(A::MyClass&, A::MyClass&) y std::swap(A::MyClass&, A::MyClass&) se definen, a continuación, el primer ejemplo de la llamada std::swap(A::MyClass&, A::MyClass&) pero la segunda no compila porque swap(obj1, obj2) sería ambigua.

    Trivia:

    ¿Por qué se llama «búsqueda de Koenig»?

    Porque fue ideado por el ex AT&T y Bell Labs investigador y programador, Andrew Koenig.

    Lectura adicional:



    1 La definición de búsqueda de Koenig como se define en el Josuttis libro, El Estándar de C++ Biblioteca: Un Tutorial y la Referencia.

    para la respuesta, pero la trivia no es correcta. Koenig no inventó la ADL, como confiesa aquí 🙂
    En el ejemplo de la crítica de la Koenig Algoritmo puede ser considerada como una «característica» de búsqueda de Koenig tanto como una «estafa». Usar std::swap (), de tal manera que es un lenguaje común: Proporcionar un ‘using std::swap()’ en caso de que una más especializada que la versión::swap() no se proporciona. Si una versión especializada de Un::swap() está disponible, le normall quiero que uno sea llamado. Esto proporciona más genericity para la swap (), ya que podemos confiar en la llamada a compilar y trabajo, pero también podemos confiar en la más especializada versión para ser utilizada si es que hay uno.
    Hay más en esto. Con std::swap usted realmente tiene que hacer que puesto que la única alternativa sería la de añadir std::swap plantilla de función explícita de especialización para su A clase. Sin embargo, si su A clase es una plantilla en sí sería parcial de especialización más que explícita de especialización. Y parcial de la especialización de la función de la plantilla no está permitido. La adición de sobrecarga de std::swap sería una alternativa, pero que está explícitamente prohibido (usted no puede agregar cosas a std espacio de nombres). Así ADL es solo camino para std::swap.
    Yo habría esperado a ver una mención de operadores sobrecargados en «la ventaja de búsqueda de koenig». el ejemplo con std::swap() parece un poco hacia atrás. Yo esperaría que el problema sea cuando std::swap() es seleccionado en lugar de la sobrecarga específicos para el tipo, A::swap(). El ejemplo con std::swap(A::MyClass&, A::MyClass&) parece engañoso. desde std nunca habría una sobrecarga específica para un tipo de usuario, no creo que sea un gran ejemplo.
    ERROR: prog.cpp:(.text.startup+0x7): undefined reference to MyNamespace::haceralgo(MyNamespace::Miclase)».

    OriginalEl autor Alok Save

  2. 54

    En Búsqueda de Koenig, si se llama a una función sin especificar sus nombres, a continuación, el nombre de una función es también buscado en el espacio de nombres(s) en el que el tipo de argumento(s) se define. Es por eso que también se conoce como Argumento Dependiente de Búsqueda de nombre, en definitiva simplemente ADL.

    Es a causa de la Búsqueda de Koenig, podemos escribir esto:

    std::cout << "Hello World!" << "\n";

    De lo contrario, tendríamos que escribir:

    std::operator<<(std::operator<<(std::cout, "Hello World!"), "\n");

    que realmente es demasiado escribir y el código se ve muy feo!

    En otras palabras, en ausencia de Búsqueda de Koenig, incluso un Hola Mundo programa se ve muy complicado.

    +1 me gusta la brevit
    Persuasivo ejemplo.
    Por favor, tenga en cuenta que std::cout es un argumento a la función, que es suficiente para permitir la ADL. ¿Te diste cuenta de eso?
    Tu pregunta tiene una respuesta larga, que no puede ser proporcionado en este espacio. Así que sólo puedo aconsejarle a leer sobre temas tales como : 1) la firma de ostream<< (como en lo que se toma como argumentos y lo devuelve). 2) los nombres completos (como std::vector o std::operator<<). 3) Un estudio más detallado del Argumento de la Búsqueda Dependiente.
    Sí, tienes razón. La función que puede tomar std::endl como argumento, es en realidad una función miembro. De todos modos, si yo uso "\n" en lugar de std::endl, entonces mi respuesta es correcta. Gracias por el comentario.

    OriginalEl autor Nawaz

  3. 25

    Tal vez lo mejor es empezar con el por qué, y sólo entonces ir al cómo.

    Cuando los espacios de nombres se introdujeron, la idea era tener todo definido en los espacios de nombres, de modo que las bibliotecas independientes no interfieren el uno con el otro. Sin embargo, que presentó un problema con los operadores. Mira por ejemplo en el código siguiente:

    namespace N
    {
      class X {};
      void f(X);
      X& operator++(X&);
    }
    
    int main()
    {
      //define an object of type X
      N::X x;
    
      //apply f to it
      N::f(x);
    
      //apply operator++ to it
      ???
    }

    Por supuesto, usted podría haber escrito N::operator++(x), pero que habría derrotado el punto entero de la sobrecarga de operadores. Por lo tanto, una solución que permite que el compilador encuentre operator++(X&) a pesar del hecho de que no estaba en su alcance. Por otro lado, aún así no debe encontrar otro operator++ definido en otro, sin relación de nombres que pueden hacer que la llamada ambigua (en este simple ejemplo, no tendría la ambigüedad, pero en ejemplos más complejos, usted podría). La solución fue el Argumento de la Búsqueda Dependiente (ADL), llamado de esa manera ya que la búsqueda depende del argumento (más exactamente, en el argumento del tipo). Desde que el sistema fue inventado por Andrew R. Koenig, también es llamado la búsqueda de Koenig.

    El truco está en que para las llamadas a la función, además de la normal de búsqueda de nombre (que busca los nombres en el ámbito en el punto de uso), se hace una segunda búsqueda en los ámbitos de los tipos de los argumentos dados a la función. Así, en el ejemplo anterior, si usted escribe x++ en principal, busca operator++ no sólo en el ámbito global, pero, además, en el ámbito en el que el tipo de x, N::X, fue definido, es decir, en namespace N. Y allí encuentra una coincidencia operator++, y por lo tanto x++ simplemente funciona. Otro operator++ definido en otro espacio de nombres, decir N2, no se encontró, sin embargo. Desde ADL no se limita a los espacios de nombres, también puede utilizar f(x) en lugar de N::f(x) en main().

    Gracias! Nunca realmente entender el por qué de su estaba allí!

    OriginalEl autor celtschk

  4. 19

    No todo es bueno, en mi opinión. La gente, incluyendo a los proveedores de compiladores, han sido insultar, ya que de su a veces lamentable comportamiento.

    ADL es responsable de una importante renovación de la gama de bucle en C++11. Para entender por qué la ADL a veces puede tener efectos no deseados, hay que considerar que no sólo los espacios de nombres donde los argumentos se definen, sino también de los argumentos de la plantilla de los argumentos de los argumentos, de los tipos de parámetros de tipos de función /pointee tipos de tipos de puntero de esos argumentos, y así sucesivamente.

    Un ejemplo del uso de impulsar

    std::vector<boost::shared_ptr<int>> v;
    auto x = begin(v);

    Esto dio lugar a una ambigüedad si el usuario utiliza el boost.gama de la biblioteca, debido a que ambos std::begin se encuentra (ADL utilizando std::vector) y boost::begin se encuentra (ADL utilizando boost::shared_ptr).

    Siempre me he preguntado qué beneficios hay para considerar argumentos de plantilla en el primer lugar.
    ¿Es justo decir que la ADL se recomienda sólo para los operadores y para su mejor escribir los espacios de nombres explícitamente para otras funciones?
    ¿También considerar los espacios de nombres de clases base de argumentos? (que estaría loco si lo hace, por supuesto).
    ¿cómo solucionar? usar std::empezar?
    Sí, std::begin borra el espacio de nombres de la ambigüedad.

    OriginalEl autor Johannes Schaub – litb

Dejar respuesta

Please enter your comment!
Please enter your name here