2009-11-11 17 views

Respuesta

12

Existe un problema porque es una macro y, por lo tanto, no puede manejar tipos que contienen comas (el preprocesador no conoce las plantillas).

También puede declarar la variable antes del ciclo, consulte documentation.

std::map<int, double> my_map; 

//1) 
typedef std::pair<int, double> MyPair; 
BOOST_FOREACH(MyPair p, my_map) { ... } 

//2) 
std::pair<int, double> p; 
BOOST_FOREACH(p, my_map) { ... } 

Editar:

Hay una complicación adicional con std::map en particular: la value_type no es std::pair<Key, Value>, pero std::pair<const Key, Value>.

Por lo tanto, si vas con el typedef, de una manera más adecuada (y la única manera si desea utilizar una referencia en el bucle foreach) es utilizar

typedef std::pair<const int, double> MyPair; 
//or 
typedef std::map<int, double>::value_type MyPair; 

BOOST_FOREACH(MyPair& ref, my_map) { ... } 

Sin embargo, que ganaron No funcionará si desea utilizar una variable declarada antes del ciclo, ya que no puede asignar una instancia std::pair<const int, double> más tarde (no se puede asignar al campo const), en cuyo caso solo puede usar pair<int, double> como se muestra en el manual de impulso.

+1

probablemente debería hacer lo siguiente: std :: map :: value_type –

+0

también en C++ 11; BOOST_FOREACH (auto & ref, my_map) {...} –

8

Si necesita iterar sobre un mapa, la forma más fácil es usar tuplas, desde conseguir la correcta escriba para typedef, es problemático. Aquí es cómo se puede utilizar tuplas:

std::map<int, double> my_map; 
int key; 
double value; 
BOOST_FOREACH(boost::tie(key, value), my_map) { ... } 

Sólo una nota, las comas va a trabajar aquí porque paréntesis se coloca alrededor de clave y valor. El preprocesador solo comprende comas y paréntesis (y c99 también requiere que comprenda las comillas). Por lo tanto, no puede analizar el <> en std::pair<int, double>. Sin embargo, podemos usar paréntesis para ayudar al preprocesador. Por ejemplo, si tenemos aa función que devuelve un contenedor que se llama así:

BOOST_FOREACH(int i, foo<int, int>()) { ... } //This won't compile 

Por lo tanto, podemos colocar paréntesis alrededor de una expresión y que ayudará a que el preprocesador:

BOOST_FOREACH(int i, (foo<int, int>())) { ... } //This will compile 

Sin embargo, en el caso de un mapa, no podemos colocar paréntesis alrededor de la declaración (porque no es una expresión). Así que esto no funcionará:

BOOST_FOREACH((std::pair<int, double> p), my_map) { ... } //This won't work 

Debido a que conseguirá transformado en algo como esto (std::pair<int, double> p) = *it, y que, por supuesto, es incorrecto C++.Pero usar un lazo funcionará:

BOOST_FOREACH(tie(key, value), my_map) { ... } //This will work 

Solo tenemos que declarar la clave y el valor fuera del ciclo (como se muestra arriba). Además, puede hacer que el ciclo tenga nombres más significativos. Puede escribir key en lugar de p.first y value en lugar de p.second.

+0

La coma entre la clave y el valor confundirá al preprocesador. – Ferruccio

+0

@Ferruccio La coma entre la clave y el valor *** *** confundirá al preprocesador debido al paréntesis entre la clave y el valor. Además, hago esto todo el tiempo cuando necesito iterar un mapa. –

+0

No tenía idea de que pudieras hacer eso con el preprocesador. – Ferruccio

2

Esto puede ser tan simple como esto:

BOOST_FOREACH(auto& p, my_map) { ... } 

Utilizando el estándar C++ 11, auto es como var en C#, lo hará

BOOST_FOREACH(std::pair<int, double>& p, my_map) { ... }