2009-04-27 10 views
44

mi piacerebbe un'iterazione su uno std :: mappa utilizzando BOOST_FOREACH e modificare i valori. Non riesco a capirlo.utilizzando BOOST_FOREACH con 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 

Ovviamente questo non cambia nulla perché non sto iterando per riferimento. Così mi sostituisco questa linea, invece (come per esempio nella documentazione Boost):

BOOST_FOREACH(IdSizePair_t &i, mmap) 

e ottengo l'errore del compilatore:

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

Qualche suggerimento?

+0

Cosa compilatore stai usando? Ho provato il tuo codice su VS2008 e ha funzionato correttamente. Ho provato anche hvint [risposta] (http://stackoverflow.com/questions/795443/using-boostforeach-with-stdmap/795482#795482) e ha funzionato. Sto usando la spinta 1.36, se questo è importante. –

+0

probabilmente hai dimenticato il &? senza quello, copia l'altra coppia, e la costanza non avrà importanza allora. –

risposta

66

Il problema riguarda il primo membro della coppia, che deve essere const. Prova questo:

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

+1. mi hai battuto per pochi secondi: D –

+0

Grazie, hvint. Questo è stato. Inoltre (dopo aver letto il tuo commento) mi sono reso conto che un altro modo per risolverlo è cambiare la prima riga del mio codice originale a questo: typedef std :: pair IdSizePair_ty; (che mi consente di scorrere per riferimento) – kmote

+0

kmote, sì, in realtà è quello che ho proposto nella mia risposta (che ho cancellato quando ho visto hvint one's). Inoltre, sai perché si comporta in questo modo? Cancellerò il mio se avrai bisogno di spiegazioni. –

4

Un'altra opzione è quella di utilizzare BOOST_FOREACH_PAIR, vedere la mia risposta qui:

BOOST_FOREACH & templates without typedef

+1

Mi piace l'aspetto di BOOST_FOREACH_PAIR, ma non vedo alcun riferimento ufficiale ad esso e non è nella versione 1.46 che sto usando.È mai stato incluso in una versione ufficiale? –

+0

Questa era solo una macro fatta in casa, non è mai stata implementata in boost. Terminato come un wontfix (a favore dei cicli basati su intervalli C++ 11) in https://svn.boost.org/trac/boost/ticket/3469 – baderous

21

questo è un vecchio thread, ma c'è una soluzione più conveniente.

impulso ha la nozione di 'adattatori gamma' che eseguono una trasformazione su intervalli iteratore. Esistono adattatori di intervallo specifici per questo caso d'uso esatto (iterazione su chiavi o valori di mappa): boost::adaptors::map_values e boost::adaptors::map_keys.

Così si potrebbe iterare valori della mappa in questo modo:

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

Maggiori informazioni here.

+0

Per questa soluzione ' 'deve essere incluso. – scai

0

A partire dal C++ 11 Considerare l'utilizzo parola chiave auto:

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