map, lambda, remove_if
So, ich habe problem mit std::map, lambda-und stl-Algorithmus(remove_if). Tatsächlich, der gleiche code mit std::list oder std::vector funktioniert gut.
Meinem test-Beispiel :
#include <map>
#include <iostream>
#include <algorithm>
struct Foo
{
Foo() : _id(0) {}
Foo(int id) : _id(id)
{
}
int _id;
};
typedef std::map<int, Foo> FooMap;
int main()
{
FooMap m;
for (int i = 0; i < 10; ++i)
m[i + 100] = Foo(i);
int removeId = 6;
//<<< Error here >>>
std::remove_if(m.begin(), m.end(), [=](const FooMap::value_type & item) { return item.second._id == removeId ;} );
for (auto & item : m )
std::cout << item.first << " = " << item.second._id << "\n";
return 0;
}
Fehlermeldung :
In file included from /usr/include/c++/4.6/utility:71:0,
from /usr/include/c++/4.6/algorithm:61,
from main.cxx:1:
/usr/include/c++/4.6/bits/stl_pair.h: In member function ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const int, _T2 = Foo, std::pair<_T1, _T2> = std::pair<const int, Foo>]’:
/usr/include/c++/4.6/bits/stl_algo.h:1149:13: instantiated from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::_Rb_tree_iterator<std::pair<const int, Foo> >, _Predicate = main()::<lambda(const value_type&)>]’
main.cxx:33:114: instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const int, Foo>::first’
Ich verstehe nicht, was hier falsch ist. So bin ich froh zu Lesen, die Ratschläge/Anweisungen darüber. Mein Ziel - verwenden Sie die neuen lambda-Stil mit std::map und algorithmen, wie remove_if.
g++ 4.6, -std=c++0x.
InformationsquelleAutor der Frage Reddy | 2012-03-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem ist, dass
std::map<K,V>::value_type
iststd::pair<const K, V>
aka.first
istconst
und nicht übertragbar. Lambda-Ausdrücke haben nichts mit dem problem zu tun hier.std::remove_if
"entfernt" Elemente durch verschieben der Elemente des Containers um, so dass alles, was nicht passt das Prädikat ist an der front, vor dem zurückgegebenen iterator. Alles, was nach der iterator ist nicht spezifiziert. Es bedeutet, dass mit einfachen Aufgabe, und da kann man nicht zuordnenconst
variable, erhalten Sie diesen Fehler.†Den Namen
remove
kann ein bisschen irreführend und in diesem Fall, Sie wirklich wollenerase_if
aber ach, das gibt es nicht. Sie haben zu tun mit der Iteration über alle Elemente und löschen Sie Sie von hand mitgekennzeichnet.erase(iterator)
:Dies ist sicher, weil Sie löschen können einzelne Knoten in den Baum, ohne die anderen Iteratoren immer ungültig. Beachten Sie, dass ich nicht erhöhen den iterator in der for-Schleife header selbst, denn das würde überspringen eines Elements in dem Fall, wo löschen Sie einen Knoten.
† Sie sollten inzwischen bemerkt haben, dass dies würde sich verheerend in der
std::map
's bestellen, das ist der Grund, warum der Schlüssel istconst
- so können Sie keinen Einfluss auf die Bestellung, in irgendeiner Weise, nachdem ein Element eingefügt wurde.InformationsquelleAutor der Antwort Xeo
Könnten Sie finden und löschen für die Karte. Es ist nicht so bequem wie remove_if, aber es ist die beste, die Sie haben.
InformationsquelleAutor der Antwort YoungJohn