Maison >développement back-end >C++ >L'initialisation de liste peut-elle gérer correctement les vecteurs de types à déplacement uniquement en C ?
L'initialisation de liste peut-elle être utilisée avec un vecteur de types à déplacement uniquement ?
Lors de l'initialisation d'un vecteur avec des types à déplacement uniquement à l'aide de syntaxe d'initialisation de liste, GCC essaie de copier les uniques_pointers dans le vecteur. Ce comportement provient du fait que unique_ptrs ne sont pas copiables.
GCC tente-t-il de copier des pointeurs correctement ?
Le comportement de GCC dans ce cas n'est pas correct. Un vecteur de unique_ptrs ne peut pas être construit en copiant les pointeurs ; à la place, la sémantique de déplacement doit être utilisée.
Solution alternative
Pour initialiser correctement un vecteur de types de déplacement uniquement, il est nécessaire d'utiliser std::make_move_iterator pour créer des itérateurs qui déplacent les éléments pointés lorsqu'ils sont déréférencés :
#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))}; }
Supplémentaire Approche
Une autre alternative, bien que moins simple, consiste à utiliser std::enable_if et une structure d'assistance rref_wrapper pour construire un vecteur de types de déplacement uniquement :
#include <utility> #include <type_traits> template<class T> struct rref_wrapper { // CAUTION - very volatile, use with care explicit rref_wrapper(T&& v) : _val(std::move(v)) {} explicit operator T() const{ return T{ std::move(_val) }; } private: T&& _val; }; // only usable on temporaries 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)); } // lvalue reference can go away template<class T> void rref(T&) = delete;
Utiliser ceci helper, le vecteur peut être initialisé 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());
Cette approche utilise std::enable_if pour garantir que rref ne peut être utilisé que temporairement, évitant ainsi toute utilisation abusive potentielle.
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!