nestle libreria library drink descargar bebida c++ boost

c++ - libreria - ¿Cómo usar BOOST_FOREACH con un impulso:: ptr_map?



descargar boost (9)

¿Cómo puedo usar BOOST_FOREACH de manera eficiente (número de caracteres / capacidad de lectura) con un boost :: ptr_map?

Kristo demostró en su respuesta que es posible usar BOOST_FOREACH con un ptr_map, pero realmente no me salvó ningún tipeo (o hace que mi código sea realmente más legible) que iterar sobre el ptr_map con un iterador:

typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair; BOOST_FOREACH(IntPair p, mymap) { int i = p.first; } // vs. boost::ptr_map<int, T>::iterator it; for (it = mymap.begin(); it != mymap.end(); ++it) { // doSomething() }

El siguiente código está en algún lugar a lo largo de las líneas que deseo. Sigue la forma estándar de cómo usar BOOST_FOREACH con un std :: map. Lamentablemente, esto no compila:

boost::ptr_map<int, T> mymap; // insert something into mymap // ... typedef pair<int, T> IntTpair; BOOST_FOREACH (IntTpair &p, mymap) { int i = p.first; }


Debe compilar sin la referencia:

BOOST_FOREACH (IntTpair p, mymap)

Creo que el problema es que los mapas en realidad no almacenan objetos como pares, sino como una estructura de árbol con el primer elemento como clave, por lo que BOOST_FOREACH no puede obtener una referencia a un par, pero puede crear una copia temporal de uno.


Este código de ejemplo compilado para mí con g ++ 4.1.2:

#include "boost/ptr_container/ptr_map.hpp" #include "boost/foreach.hpp" int main() { boost::ptr_map<int, int> mymap; typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair; BOOST_FOREACH(IntPair p, mymap) { int i = p.first; } return 0; }


Me encontré con el mismo problema hoy. Desafortunadamente, la sugerencia de Daniel no funcionará con una referencia constante a un mapa. En mi caso, el ptr_map era miembro de una clase, y quería recorrerlo en una función de miembro constante. Tomando prestado el ejemplo de Daniel, esto es lo que tuve que hacer en mi caso:

#include "boost/ptr_container/ptr_map.hpp" #include "boost/foreach.hpp" int main() { typedef boost::ptr_map<int, int> int_map; int_map mymap; const int_map& mymap_const_ref(mymap); BOOST_FOREACH(int_map::const_iterator::value_type p, mymap_const_ref) { } }

Parece que int_map::const_iterator::value_type es equivalente a boost::ptr_container_detail::ref_pair<int, const int* const> .


Como contenedores de estilo STL, los contenedores de puntero tienen un value_type que puede usar:

#include <boost/ptr_container/ptr_map.hpp> #include <boost/foreach.hpp> int main() { typedef boost::ptr_map<int, int> int_map; int_map mymap; BOOST_FOREACH(int_map::value_type p, mymap) { } }

Encuentro que usar un typedef para el contenedor hace que el código sea mucho más fácil de escribir.

Además, debe intentar evitar el uso de los contenidos de espacios de nombres de detail en boost, es una convención de impulso que contengan detalles de implementación.


using :: value_type no te permitirá const-iterate a través del contenedor. Yo uso tipos de referencia de iterador

typedef boost::ptr_map< myKey, myPtrType > MyMap; MyMap m; BOOST_FOREACH( MyMap::iterator::reference it, m ) do_something( it.second ); BOOST_FOREACH( MyMap::const_iterator::reference it, m ) do_something_const( it.second );


Al final, decidí declarar la variable de iteración antes del ciclo.

std::pair<std::string, TrailStep*> step; BOOST_FOREACH(step, m_steps) { SAFE_DELETE(step.second); }

Pero de hecho, debería haber una manera más simple. (¿Usar D en su lugar?)


Uso esta plantilla homebrew que agrega un tipo de iteración que BOOST_FOREACH puede manejar

namspace homebrew { template < class Key, class T, class Compare = std::less<Key>, class CloneAllocator = boost::heap_clone_allocator, class Allocator = std::allocator< std::pair<const Key,void*> > > class ptr_map : public boost::ptr_map<Key,T,Compare,CloneAllocator,Allocator> { public: typedef boost::ptr_container_detail::ref_pair<Key,const T* const> const_ref; typedef boost::ptr_container_detail::ref_pair<Key,T* const> ref; }; }

Supongamos que foo y bar son dos de tus tipos favoritos;)

typedef homebrew::ptr_map<foo,bar> Map; int f( const Map& m ) { BOOST_FOREACH(Map::const_ref v, m) { v.first; // foo v.second; // const bar* const } }

o

int f( Map& m ) { BOOST_FOREACH(Map::ref v, m) { v.first; // foo v.second; // bar* const } }

El que tengas que utilizar no parece depender de la forma en que lo uses en el ciclo (const o non-const) sino en la constness del mapa. Entonces, lo siguiente terminará en un error ...

int f( Map& m ) { BOOST_FOREACH(Map::const_ref v, m) // can''t use const_ref because m isn''t const { ... } }

¡Extraño! no es así?

Lo mejor para mí es que de todas las soluciones que se sugirieron aquí, esta es la primera que se maneja correctamente con la coloración de sintaxis Eclipse CDT (cuando se usa el atributo colorante de sintaxis ''Código / Problema'').


Puede intentar esta manera súper genial de iterar sobre mapas, ptr u otros: https://svn.boost.org/trac/boost/attachment/ticket/3469/foreach_field.hpp

// no typedef needed BOOST_FOREACH_FIELD((int i)(const T& t), mymap) // do something with i or t instead of first/second

No estoy seguro de que funcione con un parámetro de plantilla, pero tal vez lo usaste solo para abstracción.


Ahórrese la mecanografía y mejore la legibilidad mediante el uso de tuplas:

boost::ptr_map<int, T> mymap; int key; T * value; BOOST_FOREACH(boost::tie(key, value), mymap) { ... }