Namensräume
Varianten
Aktionen

std::forward

Von cppreference.com
< cpp‎ | utility
 
 
Dienstprogramm-Bibliotheken
Sprachunterstützung
Typunterstützung (Basistypen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programm-Dienstprogramme
Variadische Funktionen
Coroutine-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 Hilfsmittel
Relationale Operatoren (in C++20 veraltet)
Ganzzahl-Vergleichsfunktionen
(C++20)(C++20)(C++20)  
(C++20)
Swap und Typ-Operationen
(C++14)
(C++11)
forward
(C++11)
(C++11)
(C++17)
Gemeinsame Vokabulartypen
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



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

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 Rvalue std::string übergibt, wird T zu std::string abgeleitet (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() einen const lvalue std::string übergibt, wird T zu const std::string& abgeleitet, und std::forward stellt sicher, dass eine const lvalue-Referenz an foo übergeben wird.
  • Wenn ein Aufruf von wrapper() einen non-const lvalue std::string übergibt, wird T zu std::string& abgeleitet, und std::forward stellt sicher, dass eine non-const lvalue-Referenz an foo übergeben wird.
2) Leitet Rvalues als Rvalues weiter und verbietet die Weiterleitung von Rvalues als Lvalues.

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) [edit]
konvertiert das Argument in ein xvalue, wenn der Move-Konstruktor nicht wirft
(Funktionsvorlage) [edit]