C++
Transmission parfaite
Recherche…
Remarques
La transmission parfaite nécessite le transfert des références afin de préserver les qualificateurs de référence des arguments. De telles références n'apparaissent que dans un contexte déduit . C'est:
template<class T>
void f(T&& x) // x is a forwarding reference, because T is deduced from a call to f()
{
g(std::forward<T>(x)); // g() will receive an lvalue or an rvalue, depending on x
}
Ce qui suit n'implique pas un transfert parfait, car T
n'est pas déduit de l'appel du constructeur:
template<class T>
struct a
{
a(T&& x); // x is a rvalue reference, not a forwarding reference
};
C ++ 17 autorisera la déduction des arguments du modèle de classe. Le constructeur de "a" dans l'exemple ci-dessus deviendra un utilisateur d'une référence de transfert
a example1(1);
// same as a<int> example1(1);
int x = 1;
a example2(x);
// same as a<int&> example2(x);
Fonctions d'usine
Supposons que nous voulions écrire une fonction de fabrique qui accepte une liste arbitraire d'arguments et transmet ces arguments sans modification à une autre fonction. Un exemple d'une telle fonction est make_unique
, qui est utilisé pour construire en toute sécurité une nouvelle instance de T
et renvoyer un unique_ptr<T>
propriétaire de l'instance.
Les règles de langage concernant les modèles variadiques et les références rvalue nous permettent d’écrire une telle fonction.
template<class T, class... A>
unique_ptr<T> make_unique(A&&... args)
{
return unique_ptr<T>(new T(std::forward<A>(args)...));
}
L'utilisation d'ellipses ...
indique un paquet de paramètres, qui représente un nombre arbitraire de types. Le compilateur étendra ce pack de paramètres au nombre d'arguments correct sur le site d'appel. Ces arguments sont ensuite transmis au constructeur de T
utilisant std::forward
. Cette fonction est nécessaire pour préserver les qualificateurs ref des arguments.
struct foo
{
foo() {}
foo(const foo&) {} // copy constructor
foo(foo&&) {} // copy constructor
foo(int, int, int) {}
};
foo f;
auto p1 = make_unique<foo>(f); // calls foo::foo(const foo&)
auto p2 = make_unique<foo>(std::move(f)); // calls foo::foo(foo&&)
auto p3 = make_unique<foo>(1, 2, 3);