Méthode intelligente pour construire le membre de la classe std :: vector <std :: unique_ptr >

Cette question combine unique_ptr en tant que membre de la classe et la sémantique de déplacement échoue lors de la compilation avec clang et C ++ std :: vector dans le constructeur .

Mon but est de construire un wrapper

struct V_wrapper{ std::vector<std::unique_ptr > vec; V_wrapper(std::vector<std::unique_ptr > v) : vec{std::move(v)} {} }; 

Malheureusement, ce code ne comstack pas car le compilateur (Apple LLVM version 4.2) tente de copier le vecteur v qui n’est pas pris en charge. Par contre, si je std::unique_ptr un wrapper intermédiaire pour std::unique_ptr , comme suit

 struct P_wrapper{ std::unique_ptr Ptr; P_wrapper(std::unique_ptr& p) : Ptr(std::move(p)) {} }; 

et écrivez V_wrapper comme suit

 struct V_wrapper{ std::vector

vec; V_wrapper(std::vector

v) : vec{std::move(v)} {} };

alors je n’ai aucun problème. Je pense (accentuation) que cela fonctionne parce que le constructeur du vecteur réalise que vous devez utiliser la référence pour déplacer plutôt que d’essayer de copier, tout comme dans unique_ptr en tant que membre de classe et que la sémantique de déplacement échoue à la compilation avec clang .

Malheureusement, ceci conduit à la procédure de construction plutôt gênante que je std::vector<std::unique_ptr > le std::vector<std::unique_ptr > , que je l’utilise pour construire le P_wrapper et que P_wrapper l’ P_wrapper enfin pour construire le V_wrapper . Je pense que le pas intermédiaire devrait être totalement redondant! De plus, l’interface est beaucoup plus difficile à lire. L’intérêt premier du wrapper était de cacher l’implémentation de vec à l’utilisateur. Il existe maintenant un object inexplicable (ne connaissant pas le code source), P_wrapper qui sert uniquement à construire un autre object ….

Je veux éviter cela, et n’ai qu’un seul emballage. Existe-t-il un moyen de supprimer l’intermédiaire afin que je puisse revenir à la première, beaucoup plus simple implémentation de V_wrapper ?

N’utilisez pas d’initaliseurs d’appareil dentaire gratuitement; std::vector a un constructeur qui consum des listes d’initialisation. La façon évidente d’écrire ceci comstack bien pour moi:

 #include  // for std::unique_ptr #include  // for std::move #include  // for std::vector struct bar {}; struct foo { using vtype = std::vector>; foo(vtype v) : _v(std::move(v)) { } private: vtype _v; }; 

Vous devez supprimer le constructeur de copie par défaut et les opérateurs d’affectation. Ces fonctions sont définies implicitement et doivent être explicitement supprimées, car elles essaieront de copier le vecteur et son contenu (opération illégale sur un unique_ptr ).

 struct V_wrapper { public: V_wrapper(std::vector > v) : vec(std::move(v)) {} // Delete default copy constructor + assignment operator V_wrapper(const V_wrapper &) = delete; V_wrapper& operator= (const V_wrapper &) = delete; private: std::vector > vec; };