11

¿Por qué es la salida de este code:Especializada plantilla de función de los tipos de referencia

#include <iostream> 
template<typename T> void f(T param) 
{ 
    std::cout << "General" << std::endl ; 
} 
template<> void f(int& param) 
{ 
    std::cout << "int&" << std::endl ; 
} 

int main() 
{ 
    float x ; f (x) ; 
    int y ; f (y) ; 
    int& z = y ; f (z) ; 
} 

es

general
general
general

La tercera se surprizing porque la función fue especializada exactamente f o int&

Editar: Sé que la sobrecarga podría ser una solución adecuada. Solo quiero aprender la lógica detrás de esto.

+0

Tal vez porque const int y se prefiere a int & – Septagram

+0

@Septagram: const int &? –

+0

No sé si ayuda, pero si cambia la plantilla para aceptar un 'T &', entonces tanto 'f (y)' como 'f (z)' llaman a la versión 'int &'. –

Respuesta

8

El tipo de la expresión y y la expresión z es int. Una referencia que aparece en una expresión no guardará el tipo de referencia. En cambio, el tipo de expresión será el tipo al que se hace referencia, con la expresión siendo un valor l.

Por lo tanto, en ambos casos, T se deduce a int, y por lo tanto, la especialización explícita no se utiliza en absoluto.

Lo que es importante tener en cuenta (aparte de que realmente deberías usar la sobrecarga, como dijo otro chico), es que tienes un parámetro de función no de referencia en tu plantilla. Antes de realizar cualquier deducción de T con el tipo de argumento, el tipo de argumento se convertirá de las matrices en un puntero a su primer elemento (para las funciones, los argumentos se convertirán en punteros a funciones). Por lo tanto, una plantilla de función con un parámetro de función no de referencia no permite una deducción precisa de todos modos.

+1

+1 (y gracias por detectar el error en mi propia respuesta mientras estoy en ello) –

1

Una referencia es solo un alias, no un tipo. Entonces cuando llamas a f (z), coincide con la primera versión con T = int, que es una mejor opción que T = int &. Si cambia T a T &, los argumentos int e int & llamarán a la segunda versión.

+0

Si cambio T a T &, tengo error de compilación cuando 'f (2)' o 'f (" text ")' –

+0

Cambie a const. –

0

Sé que no es la respuesta, pero, en mi humilde opinión puede probar esto, con un rasgo como el enfoque en una estructura:

template<typename T> 
struct value_traits 
{ 
    static void print(){std::cout << "General" << std::endl ;} 
}; 

template<> 
struct value_traits<const long> 
{ 
    static void print(){std::cout << "const long" << std::endl ;} 
}; 

template<> 
struct value_traits<std::vector<unsigned char> > 
{ 
    static void print(){std::cout << "std::vector<unsigned char>" << std::endl ; } 
}; 

template<> 
struct value_traits<const int> 
{ 
     static void print(){std::cout << "const int" << std::endl ;} 
}; 
Cuestiones relacionadas