Heim >Backend-Entwicklung >C++ >Kann die Listeninitialisierung Vektoren von Nur-Verschiebungs-Typen in C korrekt verarbeiten?

Kann die Listeninitialisierung Vektoren von Nur-Verschiebungs-Typen in C korrekt verarbeiten?

DDD
DDDOriginal
2024-12-24 16:41:14922Durchsuche

Can List-Initialization Correctly Handle Vectors of Move-Only Types in C  ?

Kann die Listeninitialisierung mit einem Vektor von Nur-Verschiebungs-Typen verwendet werden?

Bei der Initialisierung eines Vektors mit Nur-Verschiebungs-Typen mithilfe von Mit der Listeninitialisierungssyntax versucht GCC, die Unique_Pointer in den Vektor zu kopieren. Dieses Verhalten ist auf die Tatsache zurückzuführen, dass unique_ptrs nicht kopierbar sind.

Ist GCC korrekt beim Versuch, Zeiger zu kopieren?

Das Verhalten von GCC ist in diesem Fall nicht korrekt. Ein Vektor von unique_ptrs kann nicht durch Kopieren der Zeiger erstellt werden; Stattdessen muss die Bewegungssemantik verwendet werden.

Alternative Lösung

Um einen Vektor von Nur-Verschiebungstypen ordnungsgemäß zu initialisieren, ist es notwendig, std::make_move_iterator zu verwenden Erstellen Sie Iteratoren, die die Elemente, auf die verwiesen wird, verschieben, wenn sie dereferenziert werden:

#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))};
}

Zusätzlich Ansatz

Eine andere Alternative, wenn auch nicht so einfach, besteht darin, std::enable_if und eine Hilfsstruktur rref_wrapper zu verwenden, um einen Vektor von Nur-Verschiebungstypen zu erstellen:

#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;

Verwenden Sie dies Helfer, der Vektor kann in zwei Schritten initialisiert werden:

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());

Dieser Ansatz nutzt std::enable_if, um sicherzustellen, dass rref nur auf temporären Dateien verwendet werden kann, um so möglichen Missbrauch zu verhindern.

Das obige ist der detaillierte Inhalt vonKann die Listeninitialisierung Vektoren von Nur-Verschiebungs-Typen in C korrekt verarbeiten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn