如何停止for_each()循环的迭代? for(:)不是一个可行的选择

时间:2013-11-08 23:56:58

标签: c++ c++11 visual-studio-2010

我喜欢for_each()语法,但是当条件满足时从一个语言中逃脱是不可能的(我可以抛出异常,但这似乎有点矫枉过正)。

我已经使用find_if()来做这件事,但我有一位经理觉得以这种方式使用它有点模糊。

我正在使用MSVS2010,因此无法使用for(:)

我唯一的选择是for(auto i = container.begin(); i != container.end(); ++i)吗?

6 个答案:

答案 0 :(得分:2)

我建议使用BOOST_FOREACH,这只是一个标题BTW,所以你甚至不需要构建和链接到提升。

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

如果不能选择提升,只需使用正常的for循环,就像你说的那样

for(auto i = container.begin(); i != container.end(); ++i)  

这不是什么大不了:),或者你可以升级你的编译器。如果没有看到手头的问题和您的代码,我们无法判断find_if是否模糊不清。

这是我的for_each版本,不要相信它100%提升的时间很长而且我确信我的有很小的差异,因为它太短了(也有一个名字泄漏到你的空间,IDT提升了)< strong>这是我第三次这样做,非常确定除了泄漏的变量名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;                                                                      
}    

答案 1 :(得分:2)

使用std::find_if是更好的方法。正如Scott Meyers在他的 Effective STL 一书中所说:

  

指南:首选算法调用显式循环。算法调用通常更清晰并降低复杂性。如果没有合适的算法,为什么不写呢?你会再次使用它。

std::find_ifstd::for_each一起使用会更加清晰,因为它会分离逻辑以选择要处理的项目以及处理项目的逻辑。这也有助于提高可测试性。

此外,std::find_ifstd::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);
}

您可以再次使用。

答案 2 :(得分:1)

我认为我首先要为此通用编写一个小算法:

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集合int中的所有c s,打破/如果我们得到负数,我们将使用类似这样的代码:

for_each_until(c.begin(), c.end(), f, [](int i) { return i < 0; } );

答案 3 :(得分:0)

而不是std::for_each,如何使用基于范围的for循环?

for (const auto& item : container)
{
    if (!condition_met) { continue; }

    // process item
}

答案 4 :(得分:0)

创建一个跟踪是否达到中断条件的仿函数,如果是,则立即返回。

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

答案 5 :(得分:0)

正如你从答案中看到的那样,没有你不能在没有std::for_each运行的情况下突破:

  • 抛出异常(hackery!)
  • 首先不使用std::for_each

即。 你是对的。是的,使用适当的循环。