In entrambe le chiamate di funzione, ciò che si passa alla funzione è un int &
(nel senso di: "un lvalue di tipo int
"). Quindi, presentato con la dichiarazione di inc1
, il compilatore deve dedurre T
tale che T &&
corrisponda all'argomento che hai fornito, ad esempio int &
. L'unico modo per fare ciò è supporre che T
sia int &
, perché quindi T &&
è int & &&
, che equivale a int &
. Quindi T
diventa int &
e il locale viene dichiarato come tale.
D'altra parte, nel inc2
, il compilatore deve dedurre T
tale che T &
corrisponde al tipo di argomento che hai fornito, che è ancora int &
. Questo è più semplice se si suppone che T
sia semplicemente int
, quindi questo è ciò che si ottiene per il tipo di locale quindi.
rispondere a un paio di osservazioni (che sono stati nel frattempo eliminati): Se si dispone di una funzione con un tipo di argomento predefinito, come ad esempio
poi, quando si chiama questo esempio come inc3(a)
, il compilatore applicherà qualsiasi conversione implicita necessaria all'argomento per adattarlo. Nel caso di inc3(a)
, questo significa trasformare da int &
(nel senso di lvalue) a int
(nel senso di rvalue) – che è chiamato conversione lvalue-rvalue e una conversione implicita valida. Fondamentalmente equivale a trasformare la variabile a
nel valore che rappresenta in quel momento.
Ma quando si dichiara un modello , come ad esempio inc1
e inc2
dalla questione, e l'argomento della funzione è definita in termini di un parametro di template, quindi il compilatore non è, o non solo, cercare di applicare conversioni implicite alla discussione per renderlo adatto.Invece, sarà scegliere il parametro tipo parametro T
in modo che corrisponda al tipo di argomento che hai fornito. Le regole per questo sono complicate, ma nel caso di una dichiarazione argomento di tipo T &&
, funzionano come descritto sopra. (Nel caso di una pura dichiarazione argomento T
, un argomento lvalue ancora sottoposti Ivalue a rvalue conversione e T
sarà dedotta come int
, non int &
.)
Ecco perché, mentre int &&
è un riferimento rvalue , T &&
(dove T
è un parametro di modello) non è necessariamente un riferimento di rvalue. Invece, è qualsiasi risultato dall'adattamento di T
all'argomento fornito. L'espressione T &&
in questo caso è stata quindi chiamata riferimento universale (come indicato su lvalue o riferimento di valore) – è un riferimento che diventa o un valore di valore o valore di riferimento, se necessario.
Perché dici passiamo un 'int &'? È ovvio? – perreal
@perreal Sì. Gli argomenti passati sono variabili dichiarate come 'int':' int a = 10; 'e' int b = 10; ', rispettivamente. Quando tali variabili sono usate come argomenti per funzionare chiamate, il loro tipo è 'int &' (I.e sono riferimenti lvalue). – jogojapan
Per correggere il mio commento precedente: Il tipo di queste variabili è infatti 'int &', quindi sono _valori_ (non i riferimenti lvalue. Questo termine si applica solo alle nuove variabili dichiarate come riferimenti a 'a' o' b'). – jogojapan