std::forward
| Definiert in der Header-Datei <utility> |
||
| (1) | ||
template< class T > T&& forward( typename std::remove_reference<T>::type& t ) noexcept; |
(seit C++11) (bis C++14) |
|
| template< class T > constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept; |
(seit C++14) | |
| (2) | ||
template< class T > T&& forward( typename std::remove_reference<T>::type&& t ) noexcept; |
(seit C++11) (bis C++14) |
|
| template< class T > constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept; |
(seit C++14) | |
Wenn t ein Weiterleitungsreferenz ist (ein Funktionsargument, das als Rvalue-Referenz auf einen cv-unqualifizierten Funktionsvorlagenparameter deklariert ist), leitet diese Überladung das Argument mit der Wertkategorie, die es bei der Übergabe an die aufrufende Funktion hatte, an eine andere Funktion weiter.
Wenn es beispielsweise in einem Wrapper wie dem folgenden verwendet wird, verhält sich die Vorlage wie unten beschrieben
template<class T> void wrapper(T&& arg) { // arg is always lvalue foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T }
- Wenn ein Aufruf von
wrapper()einen Rvaluestd::stringübergibt, wirdTzustd::stringabgeleitet (nichtstd::string&,const std::string&oderstd::string&&), undstd::forwardstellt sicher, dass eine Rvalue-Referenz anfooübergeben wird. - Wenn ein Aufruf von
wrapper()einen const lvaluestd::stringübergibt, wirdTzuconst std::string&abgeleitet, undstd::forwardstellt sicher, dass eine const lvalue-Referenz anfooübergeben wird. - Wenn ein Aufruf von
wrapper()einen non-const lvaluestd::stringübergibt, wirdTzustd::string&abgeleitet, undstd::forwardstellt sicher, dass eine non-const lvalue-Referenz anfooübergeben wird.
Diese Überladung ermöglicht die Weiterleitung eines Ausdrucksergebnisses (wie z. B. eines Funktionsaufrufs), das ein Rvalue oder Lvalue sein kann, als ursprüngliche Wertkategorie eines Weiterleitungsreferenzarguments.
Wenn ein Wrapper beispielsweise nicht nur sein Argument weiterleitet, sondern eine Memberfunktion für das Argument aufruft und dessen Ergebnis weiterleitet
// transforming wrapper template<class T> void wrapper(T&& arg) { foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get())); }
wobei der Typ von arg sein kann
struct Arg { int i = 1; int get() && { return i; } // call to this overload is rvalue int& get() & { return i; } // call to this overload is lvalue };
Der Versuch, einen Rvalue als Lvalue weiterzuleiten, z. B. durch Instanziierung der Form (2) mit einem Lvalue-Referenztyp T, ist ein Kompilierungsfehler.
Inhalt |
[bearbeiten] Anmerkungen
Siehe Template-Argument-Ableitung für die besonderen Regeln hinter Weiterleitungsreferenzen (T&& als Funktionsparameter verwendet) und Weiterleitungsreferenzen für weitere Details.
[bearbeiten] Parameter
| t | - | Das weiterzuleitende Objekt |
[bearbeiten] Rückgabewert
static_cast<T&&>(t)
[bearbeiten] Komplexität
Konstant.
[bearbeiten] Beispiel
Dieses Beispiel demonstriert die perfekte Weiterleitung der Parameter an das Argument des Konstruktors der Klasse T. Außerdem wird die perfekte Weiterleitung von Parameterpaketen demonstriert.
#include <iostream> #include <memory> #include <utility> struct A { A(int&& n) { std::cout << "rvalue overload, n=" << n << '\n'; } A(int& n) { std::cout << "lvalue overload, n=" << n << '\n'; } }; class B { public: template<class T1, class T2, class T3> B(T1&& t1, T2&& t2, T3&& t3) : a1_{std::forward<T1>(t1)}, a2_{std::forward<T2>(t2)}, a3_{std::forward<T3>(t3)} {} private: A a1_, a2_, a3_; }; template<class T, class U> std::unique_ptr<T> make_unique1(U&& u) { return std::unique_ptr<T>(new T(std::forward<U>(u))); } template<class T, class... U> std::unique_ptr<T> make_unique2(U&&... u) { return std::unique_ptr<T>(new T(std::forward<U>(u)...)); } auto make_B(auto&&... args) // since C++20 { return B(std::forward<decltype(args)>(args)...); } int main() { auto p1 = make_unique1<A>(2); // rvalue int i = 1; auto p2 = make_unique1<A>(i); // lvalue std::cout << "B\n"; auto t = make_unique2<B>(2, i, 3); std::cout << "make_B\n"; [[maybe_unused]] B b = make_B(4, i, 5); }
Ausgabe
rvalue overload, n=2 lvalue overload, n=1 B rvalue overload, n=2 lvalue overload, n=1 rvalue overload, n=3 make_B rvalue overload, n=4 lvalue overload, n=1 rvalue overload, n=5
[bearbeiten] Siehe auch
| (C++11) |
konvertiert das Argument in ein xvalue (Funktionsvorlage) |
| (C++11) |
konvertiert das Argument in ein xvalue, wenn der Move-Konstruktor nicht wirft (Funktionsvorlage) |