2010-09-25 17 views
7
#include <iostream> 
using namespace std; 
template<typename T> void test() 
{ 
    cout << "Called from template T"; 
} 
template<int I> void test() 
{ 
    cout << "Called from int"; 
} 
int main() 
{ 
    test<int()>();  
} 

En el fragmento anterior test<int()>() llama la primera versión y da salidaplantilla en C++

Called from template T

¿Por qué la segunda versión ser llamado?

+2

En su ejemplo int() se interpreta como un tipo int (void) (es decir, una función). Comparar con std :: tr1 :: function . – FuleSnabel

Respuesta

11

Según se resuelve ISO C++ 03 (Section 14.3/2)

En una plantilla-argumento, una ambigüedad entre un type-id y una expresión a una type-id. int() es type-id, por lo que se llama a la primera versión.

+2

Técnicamente correcto, aunque podría mencionar que al usar la prueba <2>() se llamará al segundo, ya que '2' se resuelve en' int'. – Zooba

9

Probar:

test<(int())>(); 
+4

@sbi no es una buena pista, aunque echa de menos alguna explicación. Los parens alrededor de 'int()' lo convierten en una expresión de tipo 'int'. –

+2

@Johannes: De hecho. _I_ debería haberlo intentado antes de soltar ... @tyms: Lo siento. Eliminé mi voto negativo. (Pero no voy a votar porque esto no explica por qué funcionaría el suyo.) – sbi

5

No está del todo claro para mí lo que está tratando de lograr con esto. Pero si desea utilizar una especialización de plantilla diferente cuando se instancia la plantilla con un int en lugar de cualquier otro tipo, entonces esto es la sintaxis que necesita -

#include <iostream> 

    using namespace std; 

    template<typename T> void test() 
    { 
     cout << "Called from template T"; 
    } 

    template<> void test<int>() 
    { 
     cout << "Called from int"; 
    } 


    int main() 
    { 
      test<int>(); 

    } 
+3

'+ 1' para la única respuesta que muestra cómo hacer qué, IMO, Rahul en realidad quería hacer: definir una especialización. – sbi

+0

Un poco OT: En general, diría que no se recomienda la especialización de métodos. Herb Sutter cuenta la historia mejor que yo: http://www.gotw.ca/publications/mill17.htm – FuleSnabel

+0

@FuleSnabel: evito usar sobrecarga en lugar de la plantilla de función faltante _partial_ specialization, pero siempre he usado _full_ specialization. – sbi

1

Creo que quería la segunda plantilla que se invoca cada vez T es int. John has shown you cómo hacerlo, y Benoit has shown you lo que necesita hacer para llamar realmente a la segunda función.

Su problema es que al tratar de especializantest<>() para un tipo específico (int) utilizando la sintaxis completamente equivocado, usted ha golpeado accidentalmente otra forma sintáctica válida. (Tipo de mala suerte.) Esa segunda plantilla de función está usando un parámetro de plantilla sin tipo de modelo. Además de los tipos, puede usar otras cosas como parámetros de plantilla. Entre otros (funciones, plantillas) también puede usar constantes integrales, como int. Si hubiera tratado de hacer esto con, por ejemplo, double, el código no se hubiera podido compilar.
Su segunda plantilla test<>() es sobrecarga del primero que se puede usar con enteros constantes. Es por eso que compilaría test<0>() de Benoit.

Para una especialización completa (no hay parcial especialización para las plantillas de función, sólo hay una sobrecarga; plantillas de clase, sin embargo, tienen la especialización parcial), usted tiene que proporcionar siempre una lista de parámetros plantilla vacía (template<>) y poner los tipos para especializarse detrás del identificador test<int>.

+0

Si bien he estado haciendo muchas cosas mal en todo este hilo, a menos que señale qué hay de malo en mi respuesta, no es justo rechazarlo. – sbi