2010-09-04 19 views
20

¿Por qué no se compila? (G ++ - 4,5)dirección de la función de plantilla C++

template < typename U > 
static void h() { 
} 

int main() { 
    auto p = &h<int>; // error: p has incomplete type 
} 

EDITAR: Aquí es un trabajo en torno:

template < typename U > 
static void h() { 
} 

int main() { 
    typedef decltype (&h<int>) D; 
    D p = &h<int>; // works 
} 
+1

Compila bien en Visual Studio 2010. Probablemente sea un error en GCC. Lo que podría intentar es 'decltype (& h ) p = & h ;' – Puppy

+0

Funciona con G ++ 4.6 al menos. – Maister

+0

@DeadMG: Sin "auto" ni siquiera hay necesidad de typedef, 'void (* p)() = & h ;' también compilaría. – doc

Respuesta

13

En C++ 0x esto se garantiza que funcione. Sin embargo, en C++ 03 esto no funcionaba (la parte de inicializador, es decir) y algunos compiladores aparentemente aún no lo admiten.

Además, recuerdo que la redacción C++ 0x no está claro lo que sucede con &h<int> cuando es un argumento para una plantilla de función y el parámetro correspondiente se deduce (esto es lo que se traduce a auto, conceptualmente). La intención es, sin embargo, que sea válida. Ver this defect report donde diseñaron la redacción, el ejemplo de "Nico Josuttis" y su último ejemplo.

Existe otra regla que hace cumplir la redacción pero los compiladores no están implementando correctamente. Por ejemplo, see this clang PR.

0

No compila porque el tipo de 'p' no se sabe que el compilador que es una necesidad en C++ a diferencia de algunos otros idiomas.

Trate

template < typename U > 
static void h() { 
} 

int main() { 
    auto void (*p)() = &h<int>; 
} 
+1

La palabra clave 'auto' se usa para la deducción de tipo automático. Una característica C++ 0x. – dirkgently

+0

Ok, pero en mi código real, h toma una gran cantidad de otros parámetros en función de U y otras plantillas, y no quiero especificarlos todos, ya que el tipo de p debe ser conocido por el compilador. – Thomas

+1

@dirkgenly: Oh. Todavía estoy en C++ 03, donde 'auto' es para variables automáticas – Chubsdad

0

Trate

auto p = static_cast<void(*)()>(& h<int>); 

Debido trata gcc función como una sobrecarga basados ​​en plantillas. Desde el punto de vista del gcc, es como si tuvieras h(int param) y h(float param), ¿cuál debe elegir el compilador?

Me di cuenta de cuál era el problema en versiones anteriores de gcc, pero trataré de explicarlo con más detalle. GCC no pudo deducir el tipo, porque la función de plantilla se trató como una sobrecargada. Era básicamente igual que lo tienen las siguientes:

void h(int) 
{ 
} 

void h(float) 
{ 
} 

void (*p)(int) = & h; //ok 
void (*p)(float) = & h; //ok 
auto p = & h; //error: which version of h? 

para GCC h<int> era igual sobrecargado h función con un sinfín de alternativas en función de T parámetro. Con el código proporcionado en cuestión, era O.K. hacer lo siguiente:

void (*p)() = & h<int>; 

(por eso es que no consigo typedefed "work-around")

Mientras pensaba OP quería utilizar C++ 11 auto palabra clave según lo sugerido por una etiqueta, Fundí estáticamente h<int> en void(*)(), que es una especie de no-operación, solo para engañar a gcc, porque no fue capaz de manejar las funciones de plantilla y auto correctamente.

Las funciones void h<int>() y void h<float>() deben considerarse diferentes funciones con el mismo tipo de puntero y sin sobrecargar las versiones de la función h.Cuando una instancia deben comportarse como void hInt() y void hFloat() y usted debería ser capaz de utilizar automóviles como aquí:

void hInt() 
{ 
} 

void hFloat() 
{ 
} 

auto p = hInt; 
p = hFloat; 

Pero por alguna razón de gcc eran como versiones sobrecargadas de h.

Indique los motivos de los votos a favor.

+0

No soy el que menosprecia :) De todos modos, no estoy seguro de entender su lógica: dado que está estático_casting a un tipo conocido en tiempo de compilación, ¿para qué sirve el auto? – Francesco

+0

@Francesco: sin un lanzamiento gcc arroja un error "la declaración no puede resolver la dirección de la función sobrecargada". Obtendrá el mismo error en caso de función sobrecargada (como 'void h (int)' y 'void h (float)') en cuyo caso el compilador no puede determinar qué versión elegir cuando encuentre la instrucción '& h' . Por alguna razón (creo que es algo con descubrimiento de argumentos de plantilla), la función de plantilla se trata de la misma manera que la sobrecargada. Después de haber usado static_cast como en un caso de funciones sobrecargadas, comenzó a compilarse. 'auto' se usa para deducir el tipo' p'. – doc

+0

@Francesco: obtuvieron el mismo resultado con 'typedef' que con un static_cast. Pensé que quería la palabra clave C++ 0x 'auto' ... – doc

Cuestiones relacionadas