2013-09-27 6 views
10

In der Standard-11 C++ es heißt, dass (siehe cppreference.com, siehe auch Abschnitt 20.4.2.4 des Standards) heißt es, dassWarum std :: make_tuple std :: reference_wrapper <X> Argumente in X &?

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

ein Tupel Objekt erstellt, von den Arten der Zieltyp herzuleiten von Argumenten.

Für jeden Ti in Types..., der entsprechenden Typ Vi in Vtypes...std::decay<Ti>::type ist, es sei denn Anwendung std::decay Ergebnisse in std::reference_wrapper<X> für irgendeine Art X, in welchem ​​Fall der abgeleitete Typ X& ist.

Ich frage mich: Warum werden Referenzwrapper speziell hier behandelt?

+0

Ich denke, der Hauptpunkt ist 'std :: reference_wrapper' ist ein konventioneller Marker (speziell behandelt), der vor rvalue Referenzen notwendig war, siehe http://stackoverflow.com/questions/20080493/semantics-for-wrapped-objects -referenzwert-per-standard-via-stdmove-stdref? rq = 1. Ich denke, es sollte in C++ 11 mehr nötig sein, aber die Konvention hielt an. – alfC

Antwort

11

Dies ist mehr oder weniger der Hauptzweck von reference_wrapper.

Normalerweise macht std::make_tuple immer Tupel Werte (std::decay simuliert Pass-by-value-Semantik). Gegeben int x, y; std::make_tuple(x, y); macht std::tuple<int, int>, obwohl es Types als eine Sammlung von Referenzen int&, int& abgeleitet haben wird. std::decay konvertiert diese in int, int.

reference_wrapper ermöglicht Schaffung von Tupeln von Referenzen zu erzwingen: std::make_tuple(std::ref(x), y) eine std::tuple<int&, int> machen.

Andere Teile der Standardbibliothek verwenden reference_wrapper in der gleichen Weise. Als ein Beispiel kopiert std::bind normalerweise die gebundenen Argumente in das resultierende Objekt, aber wenn Sie möchten, dass nur eine Referenz gespeichert wird, können Sie diese explizit anfordern, indem Sie eine reference_wrapper übergeben.

+0

Beachten Sie, dass es dadurch unmöglich ist, 'make_tuple' zu ​​erzeugen und ein' tuple' zu ​​erzeugen, das 'std :: reference_wrapper ' enthält, aber Sie können 'make_tuple' erzeugen und ein' tuple' erzeugen, das 'std :: reference_wrapper &' enthält. Ich finde das amüsant. – Yakk

+0

Ja, aber es gibt wenig Vorteil eines Tupels von reference_wrappers über ein Tupel von Referenzen. –

4

Ihr Titel ist irreführend: mit std::reference_wrapper<X> werden die Mitglieder zu X& statt X. Der Grund für diese Umwandlung ist, dass std::reference_wrapper<T> ein Hilfstyp ist, der einen Werttyp in einen Referenztyp umwandeln soll. Die zusätzliche Konvertierung, die erforderlich ist, um es so aussehen zu lassen, stört jedoch manchmal die Verwendung. Daher scheint das Auspacken der Referenz, wenn möglich, ein vernünftiger Ansatz zu sein: das std::tuple<...> Mitglied zu einem T& macht die Verwendung natürlicher.

0

Die Leute benutzen normalerweise std::reference_wrapper<X>, um nicht kopierbare Typen zu halten. Daher würde das Kopieren in make_tuple den Zweck übertreffen (und den Build möglicherweise zerstören, wenn der Kopierkonstruktor gelöscht wird). Aus diesem Grund verwendet es im Rückgabetyp einen Verweis (anstelle eines Werts).

Verwandte Themen