loop for_each for examples c++ stl

c++ - examples - Rompiendo en std:: for_each loop



foreach c++ examples (7)

Al utilizar el algoritmo std :: for_each, ¿cómo se interrumpe cuando se cumple una determinada condición?


Como ya lo han demostrado otros, solo se puede lograr con soluciones que IMHO ofusque el código.

Así que mi sugerencia es cambiar for_each en un bucle for for regular. Esto hará más visible para los demás que está utilizando break (y tal vez incluso continuar).


No puede hacerlo, a menos que lance una excepción, lo cual no es una buena idea porque no hace el control de flujo con excepciones.

Actualización: al parecer, Boost tiene un for_each_if que podría ayudar, pero no estás usando Boost.


Puede usar el algoritmo find_if, que detendrá y devolverá el iterador donde la condición de predicado aplicada al elemento iterado devuelve verdadero. Por lo tanto, su predicado debe cambiarse para devolver un valor booleano como la condición continuar / romper.

Sin embargo, esto es un hack, así que puedes usar los algoritmos.

Otra forma es usar BOOST_FOREACH.


Puede usar std :: any_of (o std :: all_of o std :: none_of), por ejemplo, así:

std::vector<int> a; // ... std::all_of(a.begin(), a.end(), [&](int val) { // return false if you want to break, true otherwise });

Sin embargo, esta es una solución inútil (los valores de retorno no se usan realmente para nada), y es mejor escribir su propio bucle.


Puedes romper con for_each () lanzando una excepción desde tu functor. Sin embargo, esto a menudo no es una buena idea, y hay alternativas.

Puedes retener el estado en tu functor. Si detectas la condición de "interrupción", simplemente establece una marca en tu functor y luego, para cada iteración subsiguiente, simplemente regresa sin hacer lo que tu functor hace. Obviamente, esto no detendrá la iteración, lo que puede ser costoso para grandes colecciones, pero al menos impedirá que el trabajo se realice.

Si su colección está ordenada, puede encontrar () el elemento en el que desea dividir, luego for_each desde begin () hasta el elemento find () devuelto.

Finalmente, puedes implementar un for_each_if() . De nuevo, esto no detendrá la iteración, pero no evaluará su functor, que hace el trabajo si el predicado se evalúa como falso. Aquí hay 2 tipos de for_each_xxx() , uno que toma un valor y realiza el trabajo si el operador == () se evalúa como verdadero, y otro que toma dos functors; uno que realiza una comparación como es find_if (), y otro que realiza el trabajo si el operador de la comparación evalúa como verdadero.

/* --- For each 25.1.1 template< class InputIterator, class Function, class T> Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f) template< class InputIterator, class Function, class Predicate > Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f) Requires: T is of type EqualityComparable (20.1.1) Effects: Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold: 1: *i == value 2: pred(*i) != false Returns: f Complexity: At most last - first applications of f --- */ template< class InputIterator, class Function, class Predicate > Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f) { for( ; first != last; ++first) { if( pred(*first) ) f(*first); } return f; }; template< class InputIterator, class Function, class T> Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f) { for( ; first != last; ++first) { if( *first == value ) f(*first); } return f; };


Si desea realizar algunas acciones mientras la condición no se cumple, tal vez necesite cambiar el algoritmo en algo como std::find_if ?


Tiras una excepción. Si es o no una buena idea es una especie de pregunta de estilo, ritmo @ Dan, pero puede ser más un problema con su diseño. for_each está diseñado para una especie de estilo de programación funcional, que asume implícitamente que su función se puede aplicar de manera uniforme en todo el conjunto. Por lo tanto, si necesita una interrupción, se podría considerar una condición inusual y, por lo tanto, digna de una excepción.

La otra solución, y una solución más "funcional", es escribir su función para que si no tiene efecto en algunas aplicaciones, escríbala para que no tenga efecto. Entonces, por ejemplo, si tuvieras una función de suma, haz que agregue 0 en los casos en los que hubieras "roto".