2009-04-27 34 views
44

Me gustaría iterar sobre un estándar :: map usando BOOST_FOREACH y edito los valores. No puedo entenderlo.usando 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 

Por supuesto, esto no cambia nada porque no estoy iterando por referencia. Así sustituyo esta línea en su lugar (como en el ejemplo en la documentación Boost):

BOOST_FOREACH(IdSizePair_t &i, mmap) 

y consigo el error del compilador:

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

¿Alguna sugerencia?

+0

Qué compilador está usando? Probé tu código en VS2008 y funcionó correctamente. Probé hvint's [answer] (http://stackoverflow.com/questions/795443/using-boostforeach-with-stdmap/795482#795482) también y funcionó. Estoy usando boost 1.36, si eso importa. –

+0

es probable que haya olvidado el &? sin eso, copia el otro par, y la constness no importará entonces. –

Respuesta

66

El problema es con el primer miembro del par, que debería ser const. Prueba esto:

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

+1. Me has ganado unos segundos: D –

+0

Gracias, hvint. Eso lo hizo. También (después de leer su comentario) me di cuenta de que otra forma de solucionarlo es cambiar la primera línea de mi código original a este: typedef std :: pair IdSizePair_ty; (que me permite iterar por referencia) – kmote

+0

kmote, sí, en realidad eso es lo que propuse en mi respuesta (que eliminé cuando vi la de uno). Además, ¿sabes por qué se comporta de esa manera? Voy a recuperar el mío si necesitas alguna explicación. –

4

Otra opción es utilizar BOOST_FOREACH_PAIR, véase mi respuesta aquí:

BOOST_FOREACH & templates without typedef

+1

Me gusta el aspecto de BOOST_FOREACH_PAIR, pero no veo referencias oficiales al mismo y no está en la versión 1.46 que estoy usando.¿Alguna vez se incluyó en un lanzamiento oficial? –

+0

Eso fue solo una macro casera: nunca se implementó en el impulso. Finalizado como un arreglo no deseado (a favor de los bucles basados ​​en el rango C++ 11) en https://svn.boost.org/trac/boost/ticket/3469 – baderous

21

Este es un viejo hilo, pero no es una solución más conveniente.

boost tiene la noción de 'adaptadores de rango' que realizan una transformación en los rangos de iteradores. Hay adaptadores de rango específicos para este caso de uso exacto (iteración sobre las claves o valores del mapa): boost::adaptors::map_values y boost::adaptors::map_keys.

Por lo que podría iterar sobre valores de mapa de esta manera:

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

Más información here.

+0

Para esta solución ' 'necesita ser incluido. – scai

0

A partir de C++ 11 Considere el uso de palabras clave de 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 
Cuestiones relacionadas