2013-09-27 11 views
10

Nel C++ 11 norma si afferma che (vedi cppreference.com, vedi anche la sezione 20.4.2.4 della norma) si afferma chePerché gli argomenti di std :: make_tuple trasformano std :: reference_wrapper <X> in X &?

template< class... Types > 
tuple<VTypes...> make_tuple(Types&&... args); 

Crea un oggetto tupla, dedurre il tipo di destinazione dai tipi di argomenti.

Per ogni Ti in Types..., corrispondente tipo Vi in Vtypes... è std::decay<Ti>::type salvo applicazione std::decay risultati in std::reference_wrapper<X> per qualche tipo X, nel qual caso il tipo dedotta è X&.

Mi chiedo: perché i wrapper di riferimento sono considerati speciali qui?

+0

Penso che il punto principale sia 'std :: reference_wrapper' è un marker convenzionale (trattato appositamente) che era necessario prima dei riferimenti rvalue, vedere http://stackoverflow.com/questions/20080493/semantics-for-wrapped-objects -reference-value-by-default-via-stdmove-stdref? rq = 1. Penso che dovrebbe essere più necessario in C++ 11 ma la convenzione persisteva. – alfC

risposta

11

Questo è più o meno lo scopo principale di reference_wrapper.

Normalmente, std::make_tuple rende sempre tuple di valori (std::decay simula pass-by-value semantica). Dato int x, y; std::make_tuple(x, y); fa un std::tuple<int, int>, anche se avrà dedotto Types come un pacchetto di riferimenti int&, int&. std::decay converte quelli in int, int.

reference_wrapper consente di forzare la creazione di tuple di riferimenti: std::make_tuple(std::ref(x), y) farà una std::tuple<int&, int>.

Altre parti della libreria standard utilizzano reference_wrapper allo stesso modo. Ad esempio, std::bind di solito copia/sposta gli argomenti associati nell'oggetto risultante, ma se si desidera che memorizzi solo un riferimento, è possibile richiederlo esplicitamente passando a reference_wrapper.

+0

Nota che ciò rende impossibile 'make_tuple' e genera una' tupla' contenente uno 'std :: reference_wrapper ', ma puoi 'make_tuple' e generare una' tupla' contenente 'std :: reference_wrapper &'. Lo trovo divertente. – Yakk

+0

Sì, ma c'è un piccolo vantaggio di una tupla di reference_wrappers su una tupla di riferimenti. –

4

Il titolo è fuorviante: l'utilizzo di std::reference_wrapper<X> trasforma i membri in X& anziché in X. Il motivo per cui viene eseguita questa trasformazione è che std::reference_wrapper<T> è un tipo ausiliario, pensato per trasformare un tipo di valore in un tipo di riferimento. Tuttavia, la conversione aggiuntiva necessaria per farla apparire in questo modo a volte interferisce con l'utilizzo. Pertanto, scartare il riferimento ove possibile sembra un approccio ragionevole: rendere il membro std::tuple<...> un T& rende l'utilizzo più naturale.

0

In genere le persone utilizzano std::reference_wrapper<X> per conservare tipi non copiabili. Pertanto, copiandoli in make_tuple, si ridurrebbe lo scopo (e si potrebbe interrompere la compilazione se il costruttore di copie viene cancellato). Questo è il motivo per cui usa il riferimento (anziché un valore) nel suo tipo di ritorno.

Problemi correlati