Namespaces
Variants

std::forward

Von de.cppreference.net
 
 
Dienstprogramm-Bibliothek
Sprachunterstützung
Typunterstützung (Basistypen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programm-Dienstprogramme
Variadische Funktionen
Koroutinen-Unterstützung (C++20)
Vertragsunterstützung (C++26)
Drei-Wege-Vergleich
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Allgemeine Dienstprogramme
Relationsoperatoren (veraltet in C++20)
Ganze-Zahlen-Vergleichsfunktionen
(C++20)(C++20)(C++20)    
(C++20)
Tausch und Typoperationen
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Allgemeine Vokabular-Typen
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
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)
1) Leitet lvalues entweder als lvalues oder als rvalues weiter, abhängig von T.

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 rvalue std::string übergibt, dann wird T zu std::string deduziert (nicht std::string&, const std::string& oder std::string&&), und std::forward stellt sicher, dass eine rvalue-Referenz an foo übergeben wird.
  • Wenn ein Aufruf von wrapper() ein const lvalue std::string übergibt, dann wird T zu const std::string& deduziert, und std::forward stellt sicher, dass eine const lvalue-Referenz an foo übergeben wird.
  • Wenn ein Aufruf von wrapper() ein nicht-konstantes lvalue std::string übergibt, dann wird T zu std::string& deduziert, und std::forward stellt sicher, dass eine nicht-konstante lvalue-Referenz an foo übergeben wird.
2) Leitet rvalues als rvalues weiter und verbietet die Weiterleitung von rvalues als lvalues.

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)
wandelt das Argument in einen xvalue um, wenn der Move-Konstruktor keine Ausnahme wirft
(Funktions-Template)