2009-04-27 20 views
44

Ich würde gerne über eine STD :: Map mit BOOST_FOREACH iterieren und die Werte bearbeiten. Ich verstehe es nicht ganz.mit BOOST_FOREACH mit Std :: Map

typedef std::pair<int, int> IdSizePair_t; 
std::map<int,int> mmap;  
mmap[1] = 1; 
mmap[2] = 2; 
mmap[3] = 3; 
BOOST_FOREACH(IdSizePair_t i, mmap) 
    i.second++; 
// mmap should contain {2,3,4} here 

Natürlich ändert das nichts, weil ich nicht per Referenz iteriere. So ersetzen ich diese Linie statt (gemäß dem Beispiel in der Boost-docs):

BOOST_FOREACH(IdSizePair_t &i, mmap) 

und ich erhalte den Compiler-Fehler:

error C2440: 'initializing' : 
cannot convert from 'std::pair<_Ty1,_Ty2>' to 'IdSizePair_t &' 
    with 
    [ 
     _Ty1=const int, 
     _Ty2=int 
    ] 

Irgendwelche Vorschläge?

+0

Welche Compiler verwenden Sie? Ich habe Ihren Code auf VS2008 versucht und es hat richtig funktioniert. Ich habe auch hvint's [Antwort] (http://stackoverflow.com/questions/795443/using-boostforeach-with-stdmap/795482#795482) getestet und es hat funktioniert. Ich benutze Boost 1.36, wenn das wichtig ist. –

+0

hast du wahrscheinlich das & vergessen? ohne das kopiert es das andere Paar, und die Konstanz spielt dann keine Rolle. –

Antwort

66

Das Problem ist mit dem ersten Mitglied des Paares, das const sein sollte. Versuchen Sie folgendes:

typedef std::map<int, int> map_t; 
map_t mmap; 
BOOST_FOREACH(map_t::value_type &i, mmap) 
    i.second++; 
+0

+1. Sie schlagen mich um ein paar Sekunden: D –

+0

Danke, hvint. Das hat es getan. Auch (nach dem Lesen Ihres Kommentars) erkannte ich, dass eine andere Möglichkeit, es zu beheben, ist, die erste Zeile meines ursprünglichen Codes zu ändern: typedef std :: pair IdSizePair_ty; (was mir erlaubt, per Referenz zu iterieren) – kmote

+0

kmote, ja, das ist tatsächlich, was ich in meiner Antwort vorgeschlagen habe (die ich gelöscht habe, als ich hvint eins sah). Weißt du auch, warum es sich so verhält? Ich werde meine wiederherstellen, wenn Sie eine Erklärung brauchen. –

4

Eine weitere Option ist BOOST_FOREACH_PAIR zu verwenden, siehe meine Antwort hier:

BOOST_FOREACH & templates without typedef

+1

Ich mag das Aussehen von BOOST_FOREACH_PAIR, aber ich sehe keine offiziellen Verweise darauf und es ist nicht in der Version 1.46, die ich benutze.Wurde es jemals in eine offizielle Veröffentlichung aufgenommen? –

+0

Das war nur ein selbst gemachtes Makro - es wurde nie in Boost implementiert. Beendet als Wontfix (zugunsten von C++ 11 range-based loops) unter https://svn.boost.org/trac/boost/ticket/3469 – baderous

21

Dies ist ein alter Thread, aber es gibt eine bequemere Lösung.

boost hat den Begriff 'Bereichsadapter', die eine Transformation auf Iterator-Bereiche durchführen. Für diesen exakten Anwendungsfall gibt es spezifische Bereichsadapter (Iterieren über Kartenschlüssel oder Werte): boost::adaptors::map_values und boost::adaptors::map_keys.

So könnte man Kartenwerte wie diese iterieren:

BOOST_FOREACH(int& size, mmap | boost::adaptors::map_values) 
{ 
    ++size; 
} 

Weitere Informationen here.

+0

Für diese Lösung ' 'muss enthalten sein. – scai

0

Ab ++ 11 C prüfen, mit auto Stichwort:

std::map<int,int> mmap;  
mmap[1] = 1; 
mmap[2] = 2; 
mmap[3] = 3; 

BOOST_FOREACH(auto& mpair, mmap) 
    mpair.second++; 

//mmap will contain {2,3,4} here