2014-10-16 10 views
6

In C++, se ho una funzione generica:Come funziona la deduzione del tipo per i letterali stringa in C++?

template <typename T> 
void func(T& s) 
{ 
    std::cout << "in generic\n"; 
    std::cout << typeid(s).name(); 
} 

T andranno dedotto a typeid(s).name().

Ma come mai se faccio:

func("test"); 

Tale funzione generica funziona, ma questo non lo fa:

void func(const char*& s) 
{ 
    std::cout << "in overloaded\n"; 
    std::cout << typeid(s).name(); 
} 

so che funzionerà se cambio const char*&-const char* oppure const char* const& nella firma della funzione sovraccarica e che se voglio passare un argomento alla funzione sovraccaricata, deve essere non temporaneo. Non capisco cosa sia successo a T&, non dovrebbe trasformarsi in const char*& dopo la detrazione?

risposta

4

I letterali stringa sono matrici di caratteri const. Quindi, nel caso della funzione template chiamato in questo modo:

func("test"); 

T si deduce come char const[5]. E s è un riferimento alla stringa letterale e il suo tipo è char const (&)[5]. Cioè, un riferimento a una matrice di 5 caratteri costanti.

+0

e char const (&) [5] è una matrice di riferimenti const a char? – Pavel

+2

@ paulpaul1076: No. È un riferimento a una matrice di 5 caratteri cost. Sottile differenza nella formulazione, ma piuttosto importante (per prima cosa, non si può avere una serie di riferimenti). –

+0

Grazie amico, ora ho capito – Pavel

4

Il tipo di "test" è const char[5]. Quando si chiama un modello di funzione e si utilizza un argomento per dedurre un parametro di tipo di riferimento, la conversione da matrice a puntatore fa non. Così la funzione generica deduce T essere const char[5] - si può vedere che l'output per "test" e per un const char* diversa:

template<typename T> 
void func(T& s){ 

    std::cout << "in generic\n"; 
    std::cout << typeid(s).name() << '\n'; 
} 

int main() 
{ 
    func("test"); 
    const char *c = "test"; 
    func(c); 
} 

GCC output:

in generic 
A5_c 
in generic 
PKc 

D'altra parte, nella funzione non generico , si desidera un riferimento a un puntatore non-const a const char. Tuttavia, come il tipo di "test" è const char[5], deve subire la conversione da matrice a pointer, il che significa che il risultante const char* è un temporaneo (a rvalue). Come tale, non può legarsi a un riferimento a non-const.

+1

+1 un'estensione di gcc e clang, la macro pretty-function fa un ottimo lavoro esponendo questo con i parametri del template. [** guardalo dal vivo **] (http://ideone.com/pZO23A) – WhozCraig