c++ - retornar - multiplicar elementos de una lista
obteniendo un elemento de una tupla (2)
ADL no se aplica directamente a los identificadores de plantilla , como get<0>
, por lo que el compilador realmente no se inicia en esa ruta. C ++ 11 §14.8.1 / 8 (en C ++ 03, 14.8.1 / 6):
[Nota: para nombres de funciones simples, la búsqueda dependiente del argumento (3.4.2) se aplica incluso cuando el nombre de la función no es visible dentro del alcance de la llamada. Esto se debe a que la llamada todavía tiene la forma sintáctica de una llamada de función (3.4.1). Pero cuando se usa una plantilla de función con argumentos de plantilla explícitos, la llamada no tiene la forma sintáctica correcta a menos que haya una plantilla de función con ese nombre visible en el punto de la llamada. Si no se ve tal nombre, la llamada no está sintácticamente bien formada y no se aplica la búsqueda dependiente del argumento. Si algún nombre de este tipo es visible, se aplica una búsqueda dependiente del argumento y se pueden encontrar plantillas de funciones adicionales en otros espacios de nombres.
Se va a dar un breve ejemplo. Así que la solución es bastante fácil:
#include <tuple>
template< typename > // BEGIN STUPID BUT HARMLESS HACK
void get( struct not_used_for_anything ); // END STUPIDITY
auto t = std::make_tuple(false, false, true);
bool a = get<0>(t); // Now the compiler knows to use ADL!
bool b = std::get<0>(t); // okay
Tenga en cuenta que not_used_for_anything
en lo anterior es simplemente un mecanismo de seguridad. Se pretende que sea un tipo incompleto que nunca se completa. Omitirlo también funciona, pero no es seguro porque podría chocar con una firma que podría desear.
template< typename >
void get() = delete;
Nota: la cita anterior de la Norma no es normativa, lo que significa que, en opinión del Comité, podríamos resolver esto sin explicación, porque está implícito en el resto del idioma y la gramática, en particular el hecho de que 3.4 .2 no dice nada sobre buscar ids de plantillas. ¡Sí claro!
Posible duplicado:
¿Por qué ADL no encuentra plantillas de funciones?
La llamada a get
no parece invocar la búsqueda dependiente del argumento:
auto t = std::make_tuple(false, false, true);
bool a = get<0>(t); // error
bool b = std::get<0>(t); // okay
g ++ 4.6.0 dice:
error: ''get'' was not declared in this scope
Visual Studio 2010 dice:
error C2065: ''get'': undeclared identifier
¿Por qué?
Se debe a que intenta crear una instancia explícita de la plantilla de función get
, proporcionando 0
como argumento de plantilla. En el caso de las plantillas, ADL funciona si una plantilla de función con ese nombre es visible en el punto de la llamada. Esta plantilla de función visible solo ayuda a desencadenar ADL (puede que no se use en realidad ) y luego, se puede encontrar una mejor coincidencia en otros espacios de nombres.
Tenga en cuenta que la plantilla de función que activa (o habilita) ADL, no necesita tener una definición :
namespace M
{
struct S{};
template<int N, typename T>
void get(T) {}
}
namespace N
{
template<typename T>
void get(T); //no need to provide definition
// as far as enabling ADL is concerned!
}
void f(M::S s)
{
get<0>(s); //doesn''t work - name `get` is not visible here
}
void g(M::S s)
{
using N::get; //enable ADL
get<0>(s); //calls M::get
}
En g()
, el nombre N::get
desencadena ADL al llamar a get<0>(s)
.
Demostración: http://ideone.com/83WOW
C ++ (2003) sección 14.8.1 / 6 lecturas,
[Nota: para nombres de funciones simples, la búsqueda dependiente del argumento (3.4.2) se aplica incluso cuando el nombre de la función no es visible dentro del alcance de la llamada. Esto se debe a que la llamada todavía tiene la forma sintáctica de una llamada de función (3.4.1). Pero cuando se usa una plantilla de función con argumentos de plantilla explícitos, la llamada no tiene la forma sintáctica correcta a menos que haya una plantilla de función con ese nombre visible en el punto de la llamada. Si no se ve tal nombre, la llamada no está sintácticamente bien formada y no se aplica la búsqueda dependiente del argumento. Si algún nombre de este tipo es visible, se aplica una búsqueda dependiente del argumento y se pueden encontrar plantillas de funciones adicionales en otros espacios de nombres.
[Ejemplo:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); //ill-formed: not a function call A::f<3>(b); //well-formed C::f<3>(b); //ill-formed; argument dependent lookup // applies only to unqualified names using C::f; f<3>(b); //well-formed because C::f is visible; then // A::f is found by argument dependent lookup }
—En el ejemplo] —en la nota final]