c++ argument-dependent-lookup

c++ - Por qué la búsqueda dependiente de argumentos no funciona con la plantilla de función dynamic_pointer_cast



argument-dependent-lookup (2)

Creo que la sección §14.8.1 / 6 (C ++ 03, y creo que también se aplica en C ++ 11) se aplica a este caso que se lee como,

[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]

Su caso no activa ADL porque pasa explícitamente el argumento de la plantilla y no hay ninguna plantilla con el mismo nombre disponible en el sitio donde llama a dynamic_pointer_cast .

Un truco para habilitar ADL es agregar una plantilla ficticia con el mismo nombre a su código, como se muestra a continuación:

#include <memory> struct A {}; struct B : A {}; template<int> //template parameter could be anything! void dynamic_pointer_cast(); //ADD this. NO NEED TO DEFINE IT int main() { auto x = std::make_shared<A>(); if (auto p = dynamic_pointer_cast<B>(x)); //now it should work through ADL }

Considere el siguiente programa de C ++:

#include <memory> struct A {}; struct B : A {}; int main() { auto x = std::make_shared<A>(); if (auto p = dynamic_pointer_cast<B>(x)); }

Al compilar con MSVC 2010, obtengo el siguiente error:

error C2065: ''dynamic_pointer_cast'' : undeclared identifier

El error persiste si auto es reemplazado por std::shared_ptr<A> . Cuando califico completamente la llamada con std::dynamic_pointer_cast , el programa se compila exitosamente.

Además, a gcc 4.5.1 tampoco le gusta:

error: ''dynamic_pointer_cast'' was not declared in this scope

Pensé que std::dynamic_pointer_cast habría sido elegido por la búsqueda de Koenig , ya que el tipo de x vive en el std nombres std . Que me estoy perdiendo aqui ?


La búsqueda Koenig solo se aplica a la búsqueda de funciones. Aquí, primero debe encontrar una plantilla, luego crear una instancia de ella, antes de tener una función. Para simplemente analizar el código, el compilador debe saber que dynamic_pointer_cast es una plantilla (de lo contrario, ''<'' es menor que, y no el inicio de una lista de argumentos de plantilla); hasta que el compilador sepa que dynamic_pointer_cast es una plantilla de función, ni siquiera sabe que está involucrada una llamada de función. La expresión que ve es básicamente a < b > c , donde < y > son los operadores relacionales.