Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Breaking in std::for_each loop

Tags:

c++

stl

While using std::for_each algorithm how do I break when a certain condition is satisfied?

like image 740
Naveen Avatar asked Apr 17 '09 12:04

Naveen


4 Answers

You can use std::any_of (or std::all_of or std::none_of) e.g. like this:

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

However, this is a wasteful solution (return values are not really used for anything), and you're better off writing you own loop.

like image 51
Anton Belov Avatar answered Nov 01 '22 10:11

Anton Belov


You can use std::find_if algorithm, which will stop and return the iterator to the first element where the predicate condition applied to returns true. So your predicate should be changed to return a boolean as the continue/break condition.

However, this is a hack, so you can use the algorithms.

Another way is to use BOOST_FOREACH.

like image 24
Cătălin Pitiș Avatar answered Nov 01 '22 10:11

Cătălin Pitiș


You can break from the for_each() by throwing an exception from your functor. This is often not a good idea however, and there are alternatives.

You can retain state in your functor. If you detect the 'break' condition, simply set a flag in your functor and then for each subsequent iteration simply return without doing your functor's thing. Obviously this won't stop the iteration, which might be expensive for large collections, but it will at least stop the work from being performed.

If your collection is sorted, you can find() the element that you want to break at, then do for_each from begin() to the element find() returned.

Finally, you can implement a for_each_if(). This will again not stop the iteration but will not evaluate your functor which does the work if the predicate evaluates to false. Here are 2 flavors of for_each_xxx(), one which takes a value and performs the work if operator==() evaluates to true, and another which takes two functors; one which performs a comparison ala find_if(), and the other which performs the work if the comparison operator evaluates to true.

/* ---

    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;
    };
like image 16
John Dibling Avatar answered Nov 01 '22 09:11

John Dibling


If you want do some actions while condition is not satisfied, maybe you need change algorithm on something like std::find_if?

like image 8
bayda Avatar answered Nov 01 '22 09:11

bayda