std::forward
| Definiert in Header <utility>
|
||
template< class T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
|
(1) | (seit C++11) (bis C++14) |
template< class T >
constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept;
|
(seit C++14) | |
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;
|
(2) | (seit C++11) (bis C++14) |
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
|
(seit C++14) | |
Wenn t eine Weiterleitungsreferenz ist (ein Funktionsargument, das als rvalue-Referenz auf einen cv-unqualifizierten Funktions-Template-Parameter deklariert ist), leitet diese Überladung das Argument mit der Wertkategorie an eine andere Funktion weiter, die es hatte, als es an die aufrufende Funktion übergeben wurde.
Beispielsweise, wenn es in einem Wrapper wie dem folgenden verwendet wird, verhält sich das Template 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()ein rvaluestd::stringübergibt, dann wirdTzustd::stringdeduziert (nichtstd::string&,const std::string&oderstd::string&&), undstd::forwardstellt sicher, dass eine rvalue-Referenz anfooübergeben wird. - Wenn ein Aufruf von
wrapper()ein const lvaluestd::stringübergibt, dann wirdTzuconst std::string&deduziert, undstd::forwardstellt sicher, dass eine const lvalue-Referenz anfooübergeben wird. - Wenn ein Aufruf von
wrapper()ein nicht-konstantes lvaluestd::stringübergibt, dann wirdTzustd::string&deduziert, undstd::forwardstellt sicher, dass eine nicht-konstante lvalue-Referenz anfooübergeben wird.
Diese Überladung ermöglicht es, das Ergebnis eines Ausdrucks (wie eines Funktionsaufrufs), der ein rvalue oder lvalue sein kann, als die ursprüngliche Wertkategorie eines Weiterleitungsreferenz-Arguments weiterzuleiten.
Zum Beispiel, wenn ein Wrapper sein Argument nicht nur weiterleitet, sondern eine Mitgliedsfunktion 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, ein rvalue als lvalue weiterzuleiten, z. B. durch Instanziierung der Form (2) mit dem lvalue-Referenztyp T, ist ein Compile-Zeit-Fehler.
Hinweise
Siehe
Template-Argument-Deduktion
für die speziellen Regeln hinter Forwarding-References (
T&&
als Funktionsparameter verwendet) und
Forwarding-References
für weitere Details.
Parameter
| t | - | das zu weiterleitende Objekt |
Rückgabewert
static_cast < T && > ( t )
Komplexität
Konstante.
Beispiel
Dieses Beispiel demonstriert das perfekte Weiterleiten der Parameter an das Argument des Konstruktors der Klasse
T
. Zudem wird das perfekte Weiterleiten von Parameterpaketen gezeigt.
#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
Siehe auch
|
(C++11)
|
wandelt das Argument in einen xvalue um
(Funktions-Template) |
|
(C++11)
|
wandelt das Argument in einen xvalue um, wenn der Move-Konstruktor keine Ausnahme wirft
(Funktions-Template) |