11

Perché l'uscita di questo code:Specializzata modello di funzione per i tipi di riferimento

#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) ; 
} 

è

Generale
Generale
Generale

Il terzo è Sorprendente perché la funzione era specializzata esattamente f o int&

Modifica: so che il sovraccarico potrebbe essere una soluzione adeguata. Voglio solo imparare la logica dietro.

+0

Forse perché const int & è preferito a int &? – Septagram

+0

@Septagram: const int &? –

+0

Non so se sia d'aiuto, ma se cambi il template per accettare un 'T &', allora sia 'f (y)' che 'f (z)' chiamano la versione 'int & '. –

risposta

8

Il tipo di entrambe le espressioni e l'espressione z è int. Un riferimento che appare in un'espressione non manterrà il tipo di riferimento. Invece, il tipo dell'espressione sarà il tipo di riferimento, con l'espressione che è un lvalue.

Quindi in entrambi i casi, T viene dedotto a int e pertanto la specializzazione esplicita non viene utilizzata affatto.

Ciò che è importante notare (a parte il fatto che si dovrebbe usare realmente l'overloading, come ha detto un altro utente), è che si dispone di un parametro di funzione non di riferimento nel modello. Prima di qualsiasi deduzione di T rispetto al tipo di argomento, il tipo di argomento verrà convertito da matrici in un puntatore al loro primo elemento (per le funzioni, gli argomenti verranno convertiti in puntatori di funzione). Quindi un modello di funzione con un parametro di funzione non di riferimento non consente comunque una deduzione accurata.

+1

+1 (e grazie per aver individuato l'errore nella mia risposta mentre ci sono) –

1

Un riferimento è solo un alias, non un tipo. Quindi quando si chiama f (z), corrisponde alla prima versione con T = int, che è un'opzione migliore che T = int &. Se si modifica T a T &, gli argomenti int e int & chiameranno la seconda versione.

+0

Se cambio T in T &, ho errore del compilatore quando 'f (2)' o 'f (" testo ")' –

+0

Cambialo in const. –

0

So che non è la risposta, ma, secondo me si può provare questo, con un tratto come approccio in una struttura:

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 ;} 
};