使用std :: for_each算法时如何在满足某个条件时中断?
答案 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。