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 gérer correctement les vecteurs de types à déplacement uniquement en C ?

DDD
DDDoriginal
2024-12-24 16:41:14919parcourir

Can List-Initialization Correctly Handle Vectors of Move-Only Types in 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&amp;&amp; v)
    : _val(std::move(v)) {}

  explicit operator T() const{
    return T{ std::move(_val) };
  }

private:
  T&amp;&amp; _val;
};

// only usable on temporaries
template<class T>
typename std::enable_if<
  !std::is_lvalue_reference<T>::value,
  rref_wrapper<T>
>::type rref(T&amp;&amp; v){
  return rref_wrapper<T>(std::move(v));
}

// lvalue reference can go away
template<class T>
void rref(T&amp;) = 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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn