Maison > développement back-end > C++ > Comment puis-je initialiser un vecteur avec des types à déplacement uniquement en C ?

Comment puis-je initialiser un vecteur avec des types à déplacement uniquement en C ?

Linda Hamilton
Libérer: 2025-01-01 08:55:09
original
871 Les gens l'ont consulté

How Can I Initialize a Vector with Move-Only Types in C  ?

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() };
Copier après la connexion

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))};
}
Copier après la connexion

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&amp;&amp; _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&amp;) = delete;
Copier après la connexion

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());
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal