std::forward
| 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) | |
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 rvaluestd::string, alorsTest déduit àstd::string(passtd::string&,const std::string&, oustd::string&&), etstd::forwardgarantit qu'une référence rvalue est passée àfoo. - Si un appel à
wrapper()passe une lvalue conststd::string, alorsTest déduit àconst std::string&, etstd::forwardgarantit qu'une référence lvalue const est passée àfoo. - Si un appel à
wrapper()passe une lvalue non-conststd::string, alorsTest déduit àstd::string&, etstd::forwardgarantit qu'une référence lvalue non-const est passée àfoo.
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) |
|
(C++11)
|
convertit l'argument en une xvalue si le constructeur de déplacement ne lève pas d'exception
(modèle de fonction) |