Im folgenden Szenario
%Vor%Was wäre der optimale Rückgabetyp? Meine bisherigen Gedanken sind:
Gibt den Wert r ref zurück und leitet die Funktionsargumente perfekt weiter:
%Vor%Move konstruiere den Rückgabewert:
%Vor%Versuchen Sie einen Weg zu finden, (N) RVOs zu aktivieren (obwohl ich denke, da ich die Funktionsargumente verwenden möchte, die unmöglich sind)
Gibt es ein Problem mit diesen Lösungen? Gibt es einen besseren? Was ist die beste Praxis?
Es hängt von deinen Absichten und dem Bewegungsbewusstsein deiner T
ab. Jeder Fall ist gültig, aber es gibt Unterschiede im Verhalten; das:
leitet einen Lvalue- oder Rvalue-Referenzwert perfekt weiter, so dass keine Provisorien entstehen. Wenn Sie dort ein inline
setzen (oder der Compiler stellt es für Sie), ist es so, als hätte man den Parameter an seinem Platz. Gegen "erste Sicht Intuition" wird es keinen Laufzeitfehler aufgrund der "Referenzierung" eines toten Stack-Objekts (für den Rvalue-Fall) erzeugen, da alle von uns weitergeleiteten Provisorien von einem Aufrufer über uns kommen (oder unter uns, hängt davon ab wie Sie) Denken Sie an Stapel während Funktionsaufrufen). Auf der anderen Seite, dies (im Rvalue-Fall):
wird einen Wert verschieben ( auto
wird nie &
oder &&
ableiten) und wenn T
nicht move constructible ist, dann rufen Sie einen Kopierkonstruktor auf (es wird immer eine Kopie erstellt) wenn T
eine lvalue-Referenz ist). Wenn Sie f
in einem Ausdruck verwenden, erzeugen Sie schließlich einen xvalue (und das lässt mich fragen, ob der Compiler den ursprünglichen rvalue verwenden kann, aber ich würde nicht darauf wetten).
Lange Rede, kurzer Sinn, wenn der Code, der f
verwendet, so erstellt wird, dass er sowohl rvalue- als auch lvalue-Referenzen behandelt, würde ich mit der ersten Wahl gehen, nach all dem ist die Logik std::forward
und du erstellt keine Kopien, wenn Sie Lvalue-Referenzen haben.
Für Option 1 müssen Sie zwei Vorlagenparameter verwenden, um das Weiterleiten zu ermöglichen, wenn die beiden Argumente unterschiedliche Wertkategorien haben. Es sollte
sein %Vor% Was hier tatsächlich zurückgegeben wird, ist ziemlich schwierig zu trainieren. Zuerst müssen Sie die Wertkategorien a
und b
kennen und was T
und U
als abgeleitet haben. Dann durchläuft jedes Paar, das Sie auswählen, die sehr komplizierten Regeln für den ternären Operator. Schließlich geht die Ausgabe davon durch die decltype
-Regeln, um Ihnen den tatsächlichen Rückgabetyp der Funktion zu geben.
Ich habe mich tatsächlich einmal hingesetzt und alles einmal ausgearbeitet, mit ein wenig Hilfe von SO . Soweit ich mich erinnern kann, sieht das folgendermaßen aus: Das Ergebnis wird eine veränderbare L-Wert-Referenz sein, wenn und nur wenn a
und b
Lvalue-Referenzen kompatibler Typen sind; Das Ergebnis ist eine Const lvalue-Referenz, wenn eine von a
und b
eine Konstante lvalue-Referenz ist und die andere irgendeine Art von Referenz ist; Andernfalls gibt f
einen neuen Wert zurück.
Mit anderen Worten, es macht das Richtige für ein gegebenes Paar von Argumenten - wahrscheinlich, weil sich jemand hingesetzt hat und die Regeln genau so geschrieben hat, dass es in allen Fällen das Richtige tun würde
Option 2 tut genau dasselbe wie Option 1, außer dass die decltype
-Regeln nicht zum Spielen kommen, und die Funktion wird immer einen neuen Wert zurückgeben - plain auto
leitet niemals auf a zurück Referenz.
Ich kann mir keine Option 3 vorstellen, die RVO-mäßig funktioniert, da Sie sagen, dass Sie die Argumente verwenden.
Alles in allem denke ich (1) ist die Antwort, nach der Sie suchen.
Tags und Links c++ c++11 move-semantics c++14 rvalue-reference