我喜欢这种for_each()
语法,但是在满足条件时无法从其中转义(我可以抛出异常,但这似乎有点矫枉过正)。
我曾经find_if()
这样做过,但我有一个经理觉得以这种方式使用它有点晦涩难懂。
我正在使用 MSVS2010,所以for(:)
不可用。
是我唯一的选择for(auto i = container.begin(); i != container.end(); ++i)
吗?
我喜欢这种for_each()
语法,但是在满足条件时无法从其中转义(我可以抛出异常,但这似乎有点矫枉过正)。
我曾经find_if()
这样做过,但我有一个经理觉得以这种方式使用它有点晦涩难懂。
我正在使用 MSVS2010,所以for(:)
不可用。
是我唯一的选择for(auto i = container.begin(); i != container.end(); ++i)
吗?
使用std::find_if
是更好的方法。正如 Scott Meyers 在他的Effective STL书中所说:
指南:优先使用算法调用而不是显式循环。算法调用通常更清晰并降低复杂性。如果不存在合适的算法,为什么不写呢?你会再次使用它。
使用std::find_if
withstd::for_each
更简洁,因为它将选择要处理的项目的逻辑和处理项目的逻辑分开。这也有助于提高可测试性。
此外,std::find_if
和std::for_each
可以组合在一起创建一个新的算法,例如for_each_until
,像这样:
template <class Iterator, class F, class Cond>
void for_each_until(Iterator b, Iterator e, F f, Cond cond)
{
auto stop = std::find_if(b, e, cond);
std::for_each(b, stop, f);
}
您可以再次使用它。
我建议使用BOOST_FOREACH
,这只是一个标题顺便说一句,所以你甚至不必构建和链接来提升。
#include <string>
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
std::string hello( "Hello, world!" );
BOOST_FOREACH( char ch, hello )
{
std::cout << ch;
if(ch == 'o')break;
}
return 0;
}
如果 boost 不是一个选项,只需像你说的那样使用普通的 for 循环
for(auto i = container.begin(); i != container.end(); ++i)
这没什么大不了的:),或者你可以升级你的编译器。find_if
如果没有看到手头的问题和您的代码 ,我们就无法判断是否模糊。
这是我的 for_each 版本,不要相信它 100% boost 很长,我敢肯定我的有细微差别,因为它太短了(也会将名称泄漏到您的空间中,IDT boost 就是这样做的)这个是我的第三次这样做,除了泄露的变量名之外,很确定它是完全正确的obscure_variable_name
。
#include <string>
#include <iostream>
#include <iterator>
#define AARON_FOREACH(var,container) \
if(int obscure_variable_name = 0) {} else \
for(auto var = *std::begin(container);obscure_variable_name+1;obscure_variable_name=-1) \
for(auto iter = std::begin(container); \
iter != std::end(container)?( var = *iter), true : false ; ++iter)
int main()
{
std::string hello( "Hello, world!" );
AARON_FOREACH(ch,hello)
{
std::cout << ch;
}
std::cout<<std::endl;
AARON_FOREACH(ch,hello)
{
std::cout << ch;
if(ch == 'o')break;
}
return 0;
}
我想我会先为此通用目的编写一个小算法:
template <class Iter, class F, class Cond>
void for_each_until(Iter b, Iter e, F f, Cond cond) {
for( ; b != e; ++b) {
if (cond(*b))
return;
f(*b);
}
}
有了这个,任务变得相当微不足道。例如,要执行集合中f
的所有s ,当/如果我们得到一个负数时中断,我们会使用如下代码:int
c
for_each_until(c.begin(), c.end(), f, [](int i) { return i < 0; } );
而不是std::for_each
,使用基于范围的 for 循环怎么样?
for (const auto& item : container)
{
if (!condition_met) { continue; }
// process item
}
创建一个跟踪是否达到 break 条件的函子,如果达到则立即返回。
#include <algorithm>
#include <vector>
#include <iostream>
struct addOneUntilFive {
void operator() (int& i) {
if (breakReached)
return;
if (i == 5) {
breakReached = true;
}
i += 1;
std::cout << i << std::endl;
}
bool breakReached;
} instance;
int main() {
std::vector<int> foo{1,2,3,4,5,6,7,8,9};
std::for_each(foo.begin(), foo.end(), instance);
}
正如您从答案中看到的那样,不,如果没有以下内容,您将无法摆脱std::for_each
:
std::for_each
。即你是对的。是的,使用适当的循环。