Kann eine Vektorinitialisierung mit Nur-Verschieben-Typen erreicht werden?
Die Frage stellt sich, wenn versucht wird, einen Vektor mit eindeutigen Zeigern, einem Verschieben, zu initialisieren -nur Typ. Wenn Sie auf Code wie diesen stoßen:
#include <vector> #include <memory> using move_only = std::unique_ptr<int>; std::vector<move_only> v { move_only(), move_only(), move_only() };
GCC 4.7 versucht, die eindeutigen Zeiger aus der Initialisierungsliste zu kopieren, was zu einem Kopierversuch führt, der aufgrund der reinen Verschiebungsnatur von std::unique_ptr nicht zulässig ist .
GCCs Ansatz: Ist es so? Fehlerhaft?
Die Absicht von GCC, die Zeiger zu kopieren, ist richtig, wenn man bedenkt, dass eindeutige Zeiger nicht kopierbar sind. Die verwendete Methode, das Kopieren aus der Initialisierungsliste, löst jedoch den Konstruktor für gelöschte Kopien aus.
Alternative Lösung mit Make Move Iterator
Zur Verarbeitung reiner Verschiebungstypen Bei der Vektorinitialisierung besteht ein bevorzugter Ansatz in der Verwendung von Make-Move-Iteratoren:
#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))}; }
Die von Make-Move-Iteratoren erhaltenen Iteratoren erleichtern die Bewegung von Elementen bei der Dereferenzierung, wodurch das Problem beim Kopieren gelöst wird.
Alternative Lösung mit Template-Wrappern
Ein anderer Ansatz beinhaltet die Verwendung von Template-Wrappern mit R-Wert-Referenzsemantik:
// 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&& _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&) = delete;
Obwohl diese Lösung eine Möglichkeit zur konzeptionellen Konvertierung von R-Werten in L-Werte bietet, ist sie von entscheidender Bedeutung Aufgrund der Volatilität ist Vorsicht geboten. Eine präzisere Initialisierung kann durch einen zweistufigen Prozess erreicht 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());
Das obige ist der detaillierte Inhalt vonWie kann ich einen Vektor mit Nur-Verschieben-Typen in C initialisieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!