El siguiente es un tanto "mal", pero nos ha salvado de muchos errores.
(Actualización, gracias al comentario de @Ricky65 por traerme de vuelta aquí.) C++ 11 tiene un range-based for loop que es muy superior a esto, si su compilador lo admite; sin embargo, todavía trabajamos con algunos compiladores antiguos de realmente.
#define FOREACH(iter,stlContainer) \
for (typeof(stlContainer.begin()) iter = stlContainer.begin(), \
iter##End_Cached = stlContainer.end(); \
iter != iter##End_Cached; \
++iter)
(actualizarse una vez más, el crédito a los desarrolladores de Boost.) Se basa libremente en el más complicado, pero más capaz BOOST_FOREACH
macro, pero tiene la ventaja de ser mucho más fácil con el paso a través de versiones de depuración de los casos pequeños, y no requiere una pequeña pila de encabezados boost (que en algunas bases de código/grupos está prohibida).
Usando std::for_each
es preferible, en general, pero tiene algunas desventajas:
- los usuarios deben saber mucho acerca de las interacciones entre
bind1st
/bind2nd
/ptr_fun
/mem_fun
utilizarla de manera eficaz para la "visita" no trivial - boost soluciona muchos de estos problemas, pero no todos tienen o saben aumentar
- usuarios pueden necesitar proporcionar su propio functor (por lo general una estructura) para un solo punto de uso; dichas estructuras no se pueden declarar dentro de la función que rodea el bucle, lo que lleva a la "no localidad" del código relacionado; no lee tan bien como tener la lógica en línea con el flujo del resto de la función en algunos casos
- que no siempre muy bien en línea, dependiendo del compilador
La macro FOREACH como se indica anteriormente, proporciona un par de cosas:
- como
std::for_each
, usted no conseguirá sus límites de test incorrecto (no iterar uno pasado el final, etc.)
- usará
const_iterators
sobre contenedores constantes
Tenga en cuenta que no requiere una extensión "typeof" algo no estándar.
Un uso típico podría ser:
list< shared_ptr<Thing> > m_memberList;
// later
FOREACH(iter, m_memberList)
{
if ((*iter)->getValue() < 42) {
doSomethingWith(*iter);
}
}
no estoy del todo contento con esta macro, pero ha sido muy valiosa aquí, especialmente para los programadores sin tanta experiencia en el diseño STL-conscientes.
(Por favor no dude en señalar ventajas/desventajas/defectos, voy a actualizar la respuesta.)
puedo encontrar esta pregunta realmente útil. Sin embargo, está lleno de respuestas inútiles ... +1 a todos los que contribuyeron. – AndreasT