Ecco un esempio, forse archetipo, per questo che abbiamo bisogno remove_reference
, nella realizzazione di std::move
: L'obiettivo è quello di restituire un tipo rvalue riferimento, sulla base del dedotto tipo di argomento della funzione.
Esempio: Foo x; move(x);
Qui il numero move(x)
deve restituire un tipo Foo&&
. Ma l'argomento di move
è un'espressione di tipo Foo&
. Quindi, come può la funzione move
dedurre il tipo giusto?
Il primo tentativo è quello di utilizzare ordinaria deduzione modello argomento e utilizzare un cast:
template <typename T> T && move(??? x) { return static_cast<T&&>(x); }
Ma cosa deve andare in ???
? Se diciamo T x
, allora T
sarà dedotto come Foo&
; se diciamo T & x
, quindi T = Foo
, e se diciamo T && x
, non corrisponderà affatto. La seconda versione, T & x
, sembra essere utile.
Ma allora la funzione non funziona su rvalues per cominciare (es move(Foo(...))
. In questo caso, vogliamo T && x
modo che T = Foo
e T&& = Foo&&
lo desideri. Potremmo avere due overload, ma avendo più sovraccarichi è indesiderabile perché aumenta la complessità inutilmente.Infine, se qualcuno specificasse esplicitamente il modello paramete come move<Foo&>(x)
, la funzione sarebbe mai, perché quando T = Foo&
, quindi T&& = Foo&
.
Così viene remove_reference
:
template <typename T>
typename std::remove_reference<T>::type && move(T && x)
{
return static_cast<typename std::remove_reference<T>::type &&>(x);
}
Prima di tutto, il nuovo riferimento collasso regole implicano che T
è deduce come sia Foo&
o Foo&&
nei due casi. Quindi, remove_reference
elimina il riferimento e restituisce il tipo Foo
in qualsiasi caso e l'aggiunta di &&
rende il tipo di ritorno Foo&&
desiderato.
In un riassunto semplificato: è necessario remove_reference
perché (Foo&)&&
è Foo&
e non Foo&&
. Se si scrive codice modello che richiede il tipo base di un parametro modello che può essere dedotto come U&
o U&&
, è possibile utilizzare questo modello.
La risposta è che è necessario imparare il C++ e quindi si dovrebbe avere un'idea di come chiedere la cosa giusta. Mi dispiace se questo sembra duro, ma una volta che hai una presa più sicura sui modelli e sulla deduzione argomento, sarai in grado di capirlo. Ma non c'è alcun punto che salti in profondità, * specialmente * guardando un'implementazione di una biblioteca del mondo reale. È come cercare di imparare il greco antico scavando artefatti in Persia piuttosto che leggere un libro di testo. –
@KerrekSB: A volte è molto più facile imparare da un singolo esempio ben spiegato che da un intero libro di testo. Inoltre, la maggior parte dei libri di testo non copre nemmeno questo materiale, perché sono stati scritti riferimenti -valore esistiti nella lingua. Questa è una domanda valida e ben fatta, che posso immaginare di essere utile per molte persone che stanno imparando C++. – Mankarse
@KerrekSB Questo non è esattamente qualcosa che posso cercare. Anche se accadesse attraverso la regola che ha spinto il ctor a dover fare quello che fa probabilmente non lo assocerei qui senza vedere alcun esempio. In un'altra nota, puoi per favore smettere di fiammeggiare tutti i miei post? Hai chiaramente un problema con me (non mi interessa perché). – David