Namespaces
Variants

std::forward

Depuis fr.cppreference.net
 
 
Bibliothèque d'utilitaires
Support linguistique
Support de type (types de base, RTTI)
Macros de test de fonctionnalités de la bibliothèque (C++20)
Utilitaires de programme
Fonctions variadiques
Support des coroutines (C++20)
Support des contrats (C++26)
Comparaison à trois voies
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Utilitaires généraux
Opérateurs relationnels (déprécié en C++20)
 
Défini dans l'en-tête <utility>
template< class T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
(1) (depuis C++11)
(jusqu'à C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept;
(depuis C++14)
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;
(2) (depuis C++11)
(jusqu'à C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
(depuis C++14)
1) Transfère les lvalues soit comme des lvalues, soit comme des rvalues, selon T.

Lorsque t est une référence de transfert (un argument de fonction déclaré comme une référence rvalue vers un paramètre de modèle de fonction cv-non qualifié), cette surcharge transfère l'argument à une autre fonction avec la catégorie de valeur qu'il avait lorsqu'il a été passé à la fonction appelante.

Par exemple, si utilisé dans un wrapper comme suit, le modèle se comporte comme décrit ci-dessous :

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
}
  • Si un appel à wrapper() passe une rvalue std::string, alors T est déduit à std::string (pas std::string&, const std::string&, ou std::string&&), et std::forward garantit qu'une référence rvalue est passée à foo.
  • Si un appel à wrapper() passe une lvalue const std::string, alors T est déduit à const std::string&, et std::forward garantit qu'une référence lvalue const est passée à foo.
  • Si un appel à wrapper() passe une lvalue non-const std::string, alors T est déduit à std::string&, et std::forward garantit qu'une référence lvalue non-const est passée à foo.
2) Transfère les rvalues comme des rvalues et interdit le transfert des rvalues comme des lvalues.

Cette surcharge permet de transférer le résultat d'une expression (comme un appel de fonction), qui peut être une rvalue ou une lvalue, comme la catégorie de valeur originale d'un argument de référence de transfert.

Par exemple, si un wrapper ne fait pas que transférer son argument, mais appelle une fonction membre sur l'argument et transfère son résultat :

// transforming wrapper
template<class T>
void wrapper(T&& arg)
{
    foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
}

où le type de arg peut être

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
};

Tenter de transférer une rvalue comme une lvalue, par exemple en instanciant la forme (2) avec un type de référence lvalue T, est une erreur de compilation.

Notes

Voir la déduction d'arguments de template pour les règles spéciales concernant les références de transfert ( T&& utilisé comme paramètre de fonction) et les références de transfert pour plus de détails.

Paramètres

t - l'objet à transmettre

Valeur de retour

static_cast < T && > ( t )

Complexité

Constante.

Exemple

Cet exemple démontre le transfert parfait des paramètres vers l'argument du constructeur de la classe T . Le transfert parfait des packs de paramètres est également démontré.

#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);
}

Sortie :

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

Voir aussi

(C++11)
convertit l'argument en une xvalue
(modèle de fonction)
convertit l'argument en une xvalue si le constructeur de déplacement ne lève pas d'exception
(modèle de fonction)