c++ - Bjarne está equivocado sobre este ejemplo de ADL, o tengo un error de compilación?
c++11 argument-dependent-lookup (6)
Estoy leyendo el lenguaje de programación C ++, 4ª edición (por Bjarne Stroustrup ) sobre argument-dependent-lookup . Aquí está la cita (26.3.6, ADL exagerada):
La búsqueda dependiente de argumentos (a menudo denominada ADL) es muy útil para evitar la verbosidad (14.2.4). Por ejemplo:
#include <iostream> int main() { std::cout << "Hello, world" << endl; // OK because of ADL }
Sin búsqueda dependiente de argumento, no se encontraría el manipulador
endl
. Tal como está, el compilador nota que el primer argumento para<<
es unostream
definido enstd
. Por lo tanto, buscaendl
enstd
y lo encuentra (en<iostream>
).
Y aquí está el result producido por el compilador (modo C ++ 11):
prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
std::cout << "Hello, world" << endl;
^
O este es un error en el compilador o en el libro. ¿Qué dice el estándar?
Actualizar:
Necesito aclarar un poco. Sé que la respuesta correcta es usar std::endl
. La pregunta era sobre el texto en el libro. Como ya dijo Lachlan Easton , no es solo un error tipográfico. Todo el párrafo es (probablemente) incorrecto. Puedo aceptar este tipo de error si el libro es de otro autor (menos conocido), pero estaba (y todavía estoy) en duda porque fue escrito por Bjarne.
La pista está en el nombre "búsqueda dependiente de argumento".
Es una búsqueda de nombres de funciones no calificados, que funciona según los argumentos .
No tiene nada que ver con la búsqueda de argumentos.
Bjarne se equivocó.
No es un error en el compilador. ADL se usa para buscar funciones, no argumentos . operator<<
es la función que se encuentra a través de ADL aquí al observar los parámetros std::cout
y (lo que debería ser) std::endl
.
No tengo el libro, pero parece ser un error en el libro, el hecho de que falta el calificador del espacio de nombres no tiene nada que ver con ADL. Debería ser std::endl
.
Para aquellos que dicen que es un error tipográfico, no lo es. O Bjarne cometió un error o el compilador lo tiene mal. El párrafo después del publicado por OP lee
Sin búsqueda dependiente de argumento, no se encontraría el manipulador endl. Tal como está, el compilador nota que el primer argumento para << es un ostream definido en std. Por lo tanto, busca endl en std y lo encuentra (en
<iostream>
).
Sí, es un error: el ejemplo está mal formado y no debe compilarse. ADL se aplica a nombres de funciones no calificados que introducen expresiones de llamada de función. endl
es una expresión id que intenta buscar std::endl
. endl
no introduce una expresión de llamada de función, por lo que no se utiliza la búsqueda dependiente de los argumentos, solo se utiliza la búsqueda no calificada, por lo que no se buscará std::endl
como se pretende.
Un ejemplo más simple y correcto sería:
#include <vector>
int main()
{
std::vector<int> x, y;
swap(x,y); // calls std::swap due to ADL
}
En resumen, antes de buscar una llamada de función (por ejemplo, f(x,y,z)
) con una identificación no calificada (por ejemplo, f
), primero se analizan los parámetros de la función (por ejemplo x,y,z
) para determinar su tipo . Se forma una lista de espacios de nombres asociados en función de los tipos (por ejemplo, el espacio de nombres adjunto de la definición del tipo es un espacio de nombre asociado). Estos espacios de nombres se buscan adicionalmente para la función.
La intención del ejemplo de Bjarne es mostrar la ADL de la función std::operator<<
y no std::endl
. Esto requiere una comprensión adicional de que los operadores sobrecargados son en realidad expresiones de llamada de función, por lo que x << y
significa operator<<(x,y)
, y operator<<
es un nombre no calificado, y por lo tanto ADL se aplica a él. El tipo de LHS es std::ostream
por lo que std
es un espacio de nombre asociado, y por lo tanto se encuentra std::operator<<(ostream&, ...)
.
El comentario corregido debería decir:
Sin búsquedas dependientes de argumentos, el operador
<<
sobrecargado en elstd
nombresstd
no se encontraría. Tal como está, el compilador nota que el primer argumento para << es un ostream definido en std. Por lo tanto, busca el operador<<
in std y lo encuentra (en<iostream>
).
Es un error tipográfico en el libro como los otros ya lo han señalado. Sin embargo, lo que se quiere decir en el libro es que tendríamos que escribir
std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
sin ADL. Eso es lo que Bjarne quiso decir con verbosidad.
Estoy corregido. Como señala Lachlan Easton , no es un error tipográfico sino un error en el libro. No tengo acceso a este libro por eso no pude leer ese párrafo y darme cuenta de mí mismo. Le informé este error a Bjarne para que lo corrija.
Gracioso. El mismo ejemplo está en Wikipedia y
Tenga en cuenta que
std::endl
es una función pero necesita una cualificación completa, ya que se usa como argumento para eloperator<<
(std::endl
es un puntero a la función, no una llamada a la función).
Sin duda, es un error en el libro. Sin embargo, el ejemplo std::operator<<(std::cout, "Hello, world").operator<<(std::endl);
muestra cómo ADL ayuda a reducir la verbosidad.
Gracias a gx_ por señalar mi error .