L'initialisation de vecteur avec des types de déplacement uniquement peut-elle être réalisée ?
La question se pose lorsque l'on tente d'initialiser un vecteur avec des pointeurs uniques, un déplacement -type uniquement. Lorsque vous rencontrez un code comme celui-ci :
#include <vector> #include <memory> using move_only = std::unique_ptr<int>; std::vector<move_only> v { move_only(), move_only(), move_only() };
GCC 4.7 s'efforce de copier les pointeurs uniques de la liste d'initialisation, ce qui entraîne une tentative de copie qui n'est pas autorisée en raison de la nature de déplacement uniquement de std::unique_ptr .
L'approche de GCC : est-ce Imparfait ?
L'intention de GCC de copier les pointeurs est correcte, étant donné que les pointeurs uniques ne sont pas copiables. Cependant, la méthode qu'il utilise, la copie à partir de la liste d'initialisation, déclenche le constructeur de copie supprimé.
Solution alternative utilisant Make Move Iterator
Pour gérer les types de déplacement uniquement dans initialisation du vecteur, une approche privilégiée consiste à utiliser des itérateurs make move :
#include <iterator> #include <vector> #include <memory> int main(){ using move_only = std::unique_ptr<int>; move_only init[] = { move_only(), move_only(), move_only() }; std::vector<move_only> v{std::make_move_iterator(std::begin(init)), std::make_move_iterator(std::end(init))}; }
Les itérateurs obtenus à partir des itérateurs make move facilitent l'initialisation du vecteur. mouvement des éléments lors du déréférencement, résolvant le problème de copie.
Solution alternative utilisant des wrappers de modèles
Une autre approche consiste à utiliser des wrappers de modèles avec une sémantique de référence rvalue :
// Helper type for converting rvalues to lvalues template<class T> struct rref_wrapper { explicit rref_wrapper(T&& v) : _val(std::move(v)) {} explicit operator T() const{ return T{ std::move(_val) }; } private: T&& _val; }; // Helper function to convert rvalues to rref_wrappers template<class T> typename std::enable_if< !std::is_lvalue_reference<T>::value, rref_wrapper<T> >::type rref(T&& v){ return rref_wrapper<T>(std::move(v)); } // Helper function to delete lvalue references template<class T> void rref(T&) = delete;
Bien que cette solution fournisse un moyen de convertir conceptuellement des rvalues en lvalues, il est crucial de faire preuve de prudence en raison de à sa volatilité. Une initialisation plus concise peut être obtenue grâce à un processus en deux étapes :
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()), rref(move_only()), rref(move_only()) }; std::vector<move_only> v(il.begin(), il.end());
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!