Komisches Problem mit std::map
-
Hi,
folgender Code:
typedef std::map< std::string, CacheEntry > FontCache; typedef std::map< Font*, FontCache > Cache; Cache m_cache; for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ++i ) { if ( i->second.empty() ) i = m_cache.erase( i ); // <- Fehlerzeile! }
Will nicht compilieren, Fehlermeldung:
g++ -Wall -I/usr/include/SDL -D_REENTRANT -c fontmgr.cpp -o fontmgr.o
fontmgr.cpp: In member function `void Serpentes::FontMgr::startFrame()':
fontmgr.cpp:118: Fehler: no match für »operator=« in »i = ((std::map<Serpentes::Font*, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > >, std::lessSerpentes::Font*, std::allocator<std::pair<Serpentes::Font* const, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > > > > >)this)->std::map<_Key, _Tp, _Compare, _Alloc>::erase [with _Key = Serpentes::Font, _Tp = std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > >, _Compare = std::lessSerpentes::Font*, _Alloc = std::allocator<std::pair<Serpentes::Font* const, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > > > >](i)«
/usr/lib/gcc/i686-pc-linux-gnu/3.4.3-20050110/include/g++-v3/bits/stl_tree.h:152: Anmerkung: Kandidaten sind: std::_Rb_tree_iterator<std::pair<Serpentes::Font* const, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > > > >& std::_Rb_tree_iterator<std::pair<Serpentes::Font* const, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > > > >::operator=(const std::_Rb_tree_iterator<std::pair<Serpentes::Font* const, std::map<std::string, Serpentes::FontMgr::CacheEntry, std::lessstd::string, std::allocator<std::pair<const std::string, Serpentes::FontMgr::CacheEntry> > > > >&)
make: *** [fontmgr.o] Fehler 1Jetzt rätsel ich schon lange hier rum und habe mal spaßeshalber in der STL-Dokumentation (bei SGI.com) nachgeschaut, und dort steht doch tatsächlich drin, dass std:
:erase() keinen Rückgabewert hat.
In der MSDN steht lustigerweise genau das Gegenteil, nämlich dass std:
:erase() einen Iterator auf das nächste Element zurückliefert, wie es ja auch die anderen STL-Container machen.
Wo ist jetzt mein Fehler?
ChrisM
-
Hat keinen Rückgabewert.
-
Der Struppi sagt auch void.
In den standard hab ich noch net geschaut.
Aber hier ein "Workaround" damit du das so machen kannst.typedef std::map< std::string, CacheEntry > FontCache; typedef std::map< Font*, FontCache > Cache; Cache m_cache; for ( Cache::iterator i = m_cache.begin(),tmp; i != m_cache.end(); ++i ) { if ( i->second.empty() ) { tmp = i + 1; m_cache.erase( i , tmp ); i = tmp; } }
//Edit:
ISO/IEC 14882:1998 schrieb:
void erase(iterator position);
size_type erase(const key_type& x);
void erase(iterator first, iterator last);
-
Die assoziativen Container haben sowas nicht.
-
Hi,
gut, aber wie kann ich dann sauber ein Element aus einer Map löschen und einen Iterator auf das nächste erhalten? evils Code scheint zwar zu funktionieren und läuft wahrscheinlich sogar mit jeder STL-Implementierung garantiert, aber irgendwie sieht das doch etwas gehackt aus.
Oder gibt's keine andere Möglichkeit?
ChrisM
-
Mich würde auch Mal interessieren, wieso der Standard überhaupt bei sequentiellen Containern einen iterator liefert, nicht aber bei assoziativen!?
-
ChrisM schrieb:
Hi,
gut, aber wie kann ich dann sauber ein Element aus einer Map löschen und einen Iterator auf das nächste erhalten? evils Code scheint zwar zu funktionieren und läuft wahrscheinlich sogar mit jeder STL-Implementierung garantiert, aber irgendwie sieht das doch etwas gehackt aus.
<a href= schrieb:
www.sgi.com/tech/stl/index.html">
Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.[cpp]
for ( Cache::iterator i = m_cache.begin(); i != m_cache.end(); ) // hier kein ++i
{
if ( i->second.empty() ) {
m_cache.erase( i++ );
} else {
++i;
}
}
[/cpp]Mis2com schrieb:
Mich würde auch Mal interessieren, wieso der Standard überhaupt bei sequentiellen Containern einen iterator liefert, nicht aber bei assoziativen!?
-
Hi,
ok, danke.
ChrisM
-
Mis2com schrieb:
Mich würde auch Mal interessieren, wieso der Standard überhaupt bei sequentiellen Containern einen iterator liefert, nicht aber bei assoziativen!?
Das ist die antwort:
finix schrieb:
<a href= schrieb:
www.sgi.com/tech/stl/index.html">
Map has the important property that inserting a new element into a map does not invalidate iterators that point to existing elements. Erasing an element from a map also does not invalidate any iterators, except, of course, for iterators that actually point to the element that is being erased.Weil die Iteratoren gültig bleiben muss man keinen neuen zurückgeben. bei sequentiellen containern werden die iteratoren ungültig nach nem erase daher gibt erase einen neuen zurück der gültig ist.
Ich denke das das die einzige logische Schlussfolgerung sein kann.
So far.
MfG