C++ 打破 std::for_each 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/760221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:09:17  来源:igfitidea点击:

Breaking in std::for_each loop

c++stl

提问by Naveen

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

使用 std::for_each 算法时,如何在满足特定条件时中断?

采纳答案by C?t?lin Piti?

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

您可以使用 find_if 算法,它将停止并返回迭代器,其中应用于迭代元素的谓词条件返回 true。因此,您的谓词应该更改为返回一个布尔值作为继续/中断条件。

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

但是,这是一个 hack,因此您可以使用这些算法。

Another way is to use BOOST_FOREACH.

另一种方法是使用 BOOST_FOREACH。

回答by Anton Belov

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

您可以使用 std::any_of (或 std::all_of 或 std::none_of ),例如:

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.

但是,这是一种浪费的解决方案(返回值实际上并没有用于任何事情),您最好编写自己的循环。

回答by John Dibling

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.

您可以通过从您的函子抛出异常来中断 for_each()。然而,这通常不是一个好主意,还有其他选择。

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.

如果您的集合已排序,您可以 find() 要中断的元素,然后从 begin() 到返回的元素 find() 执行 for_each 。

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_if(). 这将再次不会停止迭代,但不会评估您的函子,如果谓词评估为假,则该函子会完成工作。这里有 2 种风格for_each_xxx(),一种接受一个值并在 operator==() 评估为真时执行工作,另一种接受两个函子;一个执行比较ala find_if(),另一个执行比较运算符评估为真时的工作。

/* ---

    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;
    };

回答by bayda

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

如果您想在不满足条件的情况下执行某些操作,也许您需要更改算法,例如std::find_if

回答by lothar

As already shown by others it is only achievable with workarounds that IMHO obfuscate the code.

正如其他人已经表明的那样,只有通过恕我直言混淆代码的变通方法才能实现。

So my suggestions is to change the for_each into a regular for loop. This will make it more visible to others that you are using break (and maybe even continue).

所以我的建议是将 for_each 更改为常规的 for 循环。这将使其他人更容易看到您正在使用中断(甚至可能继续)。

回答by Dave Van den Eynde

You can't do it, unless you throw an exception, which is not a good idea because you don't do flow control with exceptions.

你不能这样做,除非你抛出异常,这不是一个好主意,因为你没有对异常进行流控制。

Update: apparently Boost has a for_each_if that mighthelp, but you're not using Boost.

更新:显然 Boost 有一个 for_each_if可能会有所帮助,但您没有使用 Boost。

回答by Charlie Martin

You throw an exception. Whether or not it's a good idea is sort of a style question, pace @Dan, but may be more of an issue with your design. for_each is intended for a sort of functional-programming style, which implicitly assumes that your function can be applied uniformly across the set. So, if you doneed to break, that could be consiered an unusual condition, and therefore worthy of an exception.

你抛出一个异常。这是否是一个好主意是一种风格问题,速度@Dan,但可能更像是您的设计问题。for_each 旨在用于一种函数式编程风格,它隐含地假设您的函数可以在整个集合中统一应用。因此,如果您确实需要中断,这可能被视为异常情况,因此值得例外。

The other solution, and a more "functional" solution, is to write your function so that if it shouldn't have an effect on some applications, then write it to have no effect. So, for example, if you had a summing function, have it add 0 in the cases you would have "broken" from.

另一种解决方案,也是一种更“功能性”的解决方案,是编写您的函数,以便如果它不应该对某些应用程序产生影响,则将其编写为无效。因此,例如,如果您有一个求和函数,在您可能会“中断”的情况下,让它加 0。