Avoir une classe Widget
avec des constructeurs par défaut et déplacer, je voudrais écrire une fonction:Comment passer des arguments rvalue et lvalue en C++?
- accepte les lvalues et rvalues de type
Widget
comme argument, - interne « se déplace » de cet argument, par exemple, à une autre instance
Widget
.
Par exemple:
Widget w;
auto p1 = pointer_from_lrvalue(Widget()); // rvalue argument
auto p2 = pointer_from_lrvalue(w); // lvalue argument
// w is guaranteed to be no longer used from now on
où pointer_from_lrvalue()
pourrait ressembler à:
std::unique_ptr<Widget> pointer_from_lrvalue(Widget w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
Une telle approche par valeur passant montre Andrei Alexandrescu dans sa fonction scopeGuard()
[ErrorHandling-slides page 48]. Cependant, l'inconvénient de cette approche est qu'il nécessite un constructeur de copie de Widget
en cas de passage d'un argument lvalue w
(au moins avec g ++ 4.9.2).
J'ai été capable de trouver les solutions suivantes pour empêcher l'appel/nécessitant un constructeur de copie. La première utilise des références lvalue et rvalue:
std::unique_ptr<Widget> pointer_from_lrvalue(Widget& w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
std::unique_ptr<Widget> pointer_from_lrvalue(Widget&& w) {
return std::unique_ptr<Widget>(new Widget(std::move(w)));
}
Le second utilise une référence universelle:
template <typename T>
std::unique_ptr<std::remove_reference_t<T>> pointer_from_lrvalue(T&& t) {
return std::unique_ptr<std::remove_reference_t<T>>
(new std::remove_reference_t<T>(std::move(t)));
}
Je me demande:
- Que ces solutions sont correctes et sont garantis pas appelez le constructeur de copie
Widget
? - Laquelle de ces deux solutions devrais-je préférer?
- Existe-t-il une autre solution, peut-être meilleure, à ce problème?