2016-11-04 2 views
1

Ich versuche zu std::move ein Element aus einem std::set und es dann aus dem Satz zu löschen:Std :: Objekte aus einem STL-Container verschieben?

std::set<some_type> the_set; 
some_type item; 

for (auto iter = the_set.begin(); iter != the_set.end(); iter++) 
{ 
    auto miter = std::make_move_iterator(iter); 
    item = std::move(*miter); 
    the_set.erase(iter); 
    break; 
} 

Der Compiler es nicht mag, wenn auch (MSVC 2015):

error C2280: 'some_type &some_type::operator =(const some_type &)': attempting to reference a deleted function 

Scheint so, als würde es versuchen, stattdessen einen Kopierkonstruktor zu verwenden, den ich nicht möchte. Wie würde ich den Move Constructor verwenden? (Ich habe die move_iterator aus Verzweiflung versucht, nicht sicher, ob es die richtige Lösung hier ist).

Antwort

3

std::set Iteratoren sind effektiv const Iteratoren (in C++ 11 und später). Auf diese Weise können Sie sie nicht ändern und die Bestellung set brechen.

Und Sie können nicht von einem const&& bewegen. Sie können also nicht aus einer set herausziehen.

C++ 17 wird Ihnen erlauben, dies zu tun, aber via a different API (PDF). Grundsätzlich müssen Sie extract the node itself from the set, dann verschieben Sie das Objekt in den Knoten und dann den Knoten zerstören (indem Sie es vom Stapel fallen lassen). Ich glaube, der Code würde in etwa so aussehen:

+0

Da in meinem Fall löschen ich direkt nach dem Umzug, konnte ich Const Cast verwenden, um den Umzug zu erreichen? Ich weiß, es ist wahrscheinlich ein bisschen hacky ... – atanamir

+2

@atanamir: Wahrscheinlich nicht. In dem Moment, in dem du es "bewegst" (und etwas tatsächlich seinen Inhalt verändert, um Daten auszutauschen), ist das 'Set' in einem inkonsistenten Zustand (die Sortierinvariante ist wahrscheinlich gebrochen). Die Algorithmen, die zum Entfernen des Objekts verwendet werden, beruhen auf dieser Invariante (heck, sie verlassen sich darauf, dass das Objekt für Dinge wie "operator <" -Anrufe in einem brauchbaren Zustand ist und die einzige Garantie, die du bekommst, nachdem du dich von etwas entfernt hast dass es möglich ist, es neu zuzuweisen oder zu zerstören, nichts anderes ist erlaubt, es könnte "NULL" -Zeiger haben, die sonst illegal sind. Versuche nicht, dies zu tun. – ShadowRanger

+2

@atanamir: Das heißt, sieht so aus, als ob C++ 17 ['std :: set :: extract'] (http://en.cppreference.com/w/cpp/container/set/extract) einführen würde was du versuchst zu tun (vorausgesetzt, ich lese es richtig). – ShadowRanger

Verwandte Themen