2016-03-30 16 views
11

sto leggendo il reference collapsing rules e ho una domanda: perché se mi passa un rvalue Un arvalue per spedizioni riferimenti

template<typename T> 
void foo(T&&); 

T si deduce di essere un?

ad es. se passaggio std::string() alla funzione T viene dedotto per essere std::string, perché non std::string&&? Avrebbe avuto più senso per me, qual è la logica alla base della deduzione dello T al tipo stesso?

risposta

11

Questo semplicemente si allinea con quello che ci aspettiamo, in generale, dal tipo di modello deduzione:

template <class T> void vfoo(T); 
template <class T> void lfoo(T&); 
template <class T> void cfoo(T const&); 
template <class T> void ffoo(T&&); 

std::string x; 
vfoo(x);   // deduce T = std::string 
lfoo(x);   // deduce T = std::string 
cfoo(x);   // deduce T = std::string 
ffoo(x);   // deduce T = std::string& ! 
ffoo(std::move(x)); // deduce T = std::string 

Da the original paper, sottolineatura mia:

Quando dedurre un tipo di modello di funzione con una corrispondenza argomento lvalue a un riferimento di rvalue, il tipo è dedotto come un tipo di riferimento di lvalue. Quando viene fornita una deduzione per argomento rvalue, la detrazione di tipo procede esattamente come con altri tipi.

E 'il caso detrazione lvalue che è l'unica eccezione, che è il motivo per cui si ottiene una frase in più nelle regole di deduzione tipo. Il caso limite è tipico: si allinea con il semplice modello mentale di incollare nei tipi dedotti per vedere quale funzione si finisce. Chiamato T&& con un std::string? Ottieni T = std::string in modo che l'argomento sia std::string&&. Dai un'occhiata.

3

Poiché il tipo di parametro funzione ha & & e si deduce la parte "T" dell'espressione.

Quindi, 'passando' std::string&& a T&& dedurrà T come std::string.

Sostituire std::string come T nell'espressione T&& produce std::string&&.

È simile alla deduzione di T nell'espressione T const&; quando "passato" a std::string mediante riferimento const, la parte T viene dedotta come std::string.

+2

L'ultima frase è sbagliata. 'modello void foo (T)' non dedurrà mai un tipo di riferimento. – Oktalist

+0

@Oktalist hai ragione - l'ho rimosso. – Pete