打破std :: for_each循环

时间:2009-04-17 12:30:17

标签: c++ stl

使用std :: for_each算法时如何在满足某个条件时中断?

7 个答案:

答案 0 :(得分:21)

您可以使用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
  });

然而,这是一个浪费的解决方案(返回值并没有真正用于任何事情),你最好写自己的循环。

答案 1 :(得分:14)

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

您可以在您的仿函数中保留状态。如果你检测到'break'条件,只需在你的仿函数中设置一个标志,然后对于每个后续的迭代,只需返回而不做你的仿函数的事情。显然,这不会停止迭代,这对于大型集合来说可能是昂贵的,但它至少会阻止工作的执行。

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

最后,您可以实施for_each_if()。这将再次不会停止迭代,但是如果谓词的计算结果为false,则不会评估您的函数。这里有两种for_each_xxx(),一种取值,如果operator ==()计算结果为true,另一种取两个仿函数;一个执行比较ala find_if(),另一个执行工作,如果比较运算符的计算结果为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;
    };

答案 2 :(得分:13)

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

但是,这是一个黑客,所以你可以使用这些算法。

另一种方法是使用BOOST_FOREACH。

答案 3 :(得分:6)

如果你想在不满足条件的情况下做一些动作,也许你需要改变std::find_if之类的算法?

答案 4 :(得分:4)

正如其他人已经表明的那样,只有通过IMHO模糊代码的变通方法才能实现。

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

答案 5 :(得分:2)

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

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

答案 6 :(得分:0)

你抛出异常。无论这是一个好主意是一种风格问题,节奏@Dan,但可能更多的是你的设计问题。 for_each用于某种函数式编程风格,它隐含地假设您的函数可以在整个集合中统一应用。所以,如果你需要打破,那可能会被认为是一个不寻常的条件,因此值得例外。

另一个解决方案,以及一个更“功能”的解决方案是编写您的函数,以便它不会对某些应用程序产生影响,然后将其写入无效。因此,例如,如果你有一个求和函数,那么在你将“破坏”的情况下将它加0。