En el lenguaje de programación C++ , la búsqueda dependiente de argumentos ( ADL ), o búsqueda de nombre dependiente de argumentos , [ 1 ] se aplica a la búsqueda de un nombre de función no calificado según los tipos de argumentos pasados a la llamada a la función . Este comportamiento también se conoce como búsqueda de Koenig , ya que a menudo se le atribuye a Andrew Koenig , aunque él no es su inventor. [ 2 ]
Durante la búsqueda dependiente de argumentos, se pueden consultar otros espacios de nombres no considerados en la búsqueda normal, donde el conjunto de espacios de nombres a buscar depende de los tipos de los argumentos de la función. Específicamente, el conjunto de declaraciones descubiertas durante el proceso ADL, y consideradas para la resolución del nombre de la función, es la unión de las declaraciones encontradas mediante la búsqueda normal con las declaraciones encontradas al buscar en el conjunto de espacios de nombres asociados con los tipos de los argumentos de la función.
Ejemplo
Un ejemplo de ADL se ve así:
espacio de nombres foo { clase Bar { // ... };void baz ( Bar & a , int i ) { // ... } }int main () { foo :: Bar a ; baz ( a , 0 ); // Llama a foo::baz. }Aunque elprincipalLa función no está en el espacio de nombres foo, ni el espacio de nombres está fooen el ámbito, la funciónfoo::baz(Bar&, int)Se encuentra debido a los tipos declarados de los argumentos reales en la instrucción de llamada a la función.
Un patrón común en la biblioteca estándar de C++ es declarar operadores sobrecargados que se encontrarán de esta manera. Por ejemplo, este sencillo programa "Hola Mundo" no compilaría si no fuera por ADL:
importar std ;int main () { std :: string str = "hola mundo" ; std :: cout << str ; }El uso <<es equivalente a llamar operator<<sin el std::calificador. Sin embargo, en este caso, la sobrecarga del operador << que funciona para stringestá en el stdespacio de nombres, por lo que se requiere ADL para poder usarlo.
El siguiente código funcionaría sin ADL (que de todos modos se le aplica):
importar std ;int main () { std :: cout << 5 ; }Funciona porque el operador de salida para enteros es una función miembro de la std::ostreamclase, que es el tipo de cout. Por lo tanto, el compilador interpreta esta instrucción como
std :: cout.operator << ( 5 ) ;que puede resolver durante la búsqueda normal. Sin embargo, considérese que, por ejemplo, la const char*sobrecarga operator<<es una función que no pertenece al stdespacio de nombres y, por lo tanto, requiere ADL para una búsqueda correcta:
// Imprimirá la cadena de caracteres proporcionada como se espera // utilizando ADL derivado del tipo de argumento std::cout operator << ( std :: cout , "Hola" )// llama a una función miembro ostream del operador << // que toma un void const*, que imprimirá la dirección de // la cadena de caracteres proporcionada en lugar del contenido de la cadena de caracteres std :: cout.operator << ( "Hola " )Otro ejemplo es la función stdno miembro sobrecargada del espacio de nombres operator<<para manejar cadenas:
// equivalente a // operator<<(std::cout, str) // El compilador busca en el espacio de nombres std usando ADL // debido al tipo std::string del parámetro str y std::cout std :: cout << str ;Como señala Koenig en una nota personal, [ 2 ] sin ADL el compilador indicaría un error que afirma que no pudo encontrarlo operator<<ya que la instrucción no especifica explícitamente que se encuentra en el stdespacio de nombres.
Interfaces
Las funciones encontradas por ADL se consideran parte de la interfaz de una clase. En la biblioteca estándar de C++, varios algoritmos utilizan llamadas no cualificadas desde swapdentro del stdespacio de nombres. Como resultado, std::swapse utiliza la función genérica si no se encuentra ninguna otra, pero si estos algoritmos se utilizan con una clase de terceros, Foo, que se encuentra en otro espacio de nombres que también contiene , se utilizará swap(Foo&, Foo&)esa sobrecarga de .swap
Crítica
Si bien ADL hace que sea práctico que las funciones definidas fuera de una clase se comporten como si fueran parte de la interfaz de esa clase, hace que los espacios de nombres sean menos estrictos y, por lo tanto, puede requerir el uso de nombres completamente calificados cuando de otro modo no serían necesarios. Por ejemplo, la biblioteca estándar de C++ hace un uso extensivo de llamadas no calificadas para std::swapintercambiar dos valores. La idea es que luego se puede definir una versión propia swapen un espacio de nombres propio y se utilizará dentro de los algoritmos de la biblioteca estándar. En otras palabras, el comportamiento de
espacio de nombres foo { clase Bar { // ... }; }Barra a ; Barra b ;std :: swap ( a , b );puede o no ser el mismo que el comportamiento de
using std :: swap ; swap ( a , b );(donde ay bson de tipo foo::Bar) porque si foo::swap(foo::Bar&, foo::Bar&)existe, el segundo de los ejemplos anteriores lo llamará mientras que el primero no. Además, si por alguna razón tanto foo::swap(foo::Bar&, foo::Bar&)como std::swap(foo::Bar&, foo::Bar&)están definidos, entonces el primer ejemplo llamará std::swap(foo::Bar&, foo::Bar&)pero el segundo no compilará porque swap(a, b)sería ambiguo.
En general, la dependencia excesiva de ADL puede generar problemas semánticos . Si una biblioteca lib1espera que las llamadas no calificadas foo(T)tengan un significado y otra biblioteca lib2espera que tengan otro, entonces los espacios de nombres pierden su utilidad. Sin embargo, si lib1espera lib1::foo(T)que tenga un significado y lib2hace lo mismo, entonces no hay conflicto, pero las llamadas a foo(T)tendrían que estar completamente calificadas (es decir, lib1::foo(x)en contraposición a using lib1::foo; foo(x);) para evitar que ADL interfiera.
Referencias
- ↑ "Borrador de trabajo, estándar para el lenguaje de programación C++" (PDF) . JTC1/SC22/WG21 . 19 de octubre de 2005. Capítulo 3.4.2 – Búsqueda de nombres dependiente de argumentos – pág. 2. Archivado del original (PDF) el 14 de diciembre de 2005. Recuperado el 13 de marzo de 2012 .
- 1 2 "Una nota personal sobre la búsqueda dependiente de argumentos" . 3 de mayo de 2012. Archivado del original el 17 de marzo de 2018. Recuperado el 7 de febrero de 2014 .
Enlaces externos
- Búsqueda dependiente de argumentos
- ¿Qué hay en una clase? – El principio de interfaz de Herb Sutter
- Espacios de nombres y el principio de interfaz, por Herb Sutter
- Por qué odio los espacios de nombres, por Danny Kalev
- "Una propuesta modesta: Cómo mejorar las actividades de la vida diaria (revisión 2)" por Herb Sutter
- C++