4

我喜欢这种for_each()语法,但是在满足条件时无法从其中转义(我可以抛出异常,但这似乎有点矫枉过正)。

我曾经find_if()这样做过,但我有一个经理觉得以这种方式使用它有点晦涩难懂。

我正在使用 MSVS2010,所以for(:)不可用。

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

4

6 回答 6

2

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

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

使用std::find_ifwithstd::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);
}

您可以再次使用它。

于 2013-11-09T05:57:37.807 回答
2

我建议使用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;                                                                      
}    
于 2013-11-09T00:20:24.363 回答
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的所有s ,当/如果我们得到一个负数时中断,我们会使用如下代码:intc

for_each_until(c.begin(), c.end(), f, [](int i) { return i < 0; } );
于 2013-11-09T03:12:45.500 回答
0

而不是std::for_each,使用基于范围的 for 循环怎么样?

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

    // process item
}
于 2013-11-09T00:03:07.477 回答
0

创建一个跟踪是否达到 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);
}
于 2013-11-09T00:06:24.820 回答
0

正如您从答案中看到的那样,不,如果没有以下内容,您将无法摆脱std::for_each

  • 抛出异常(黑客!)
  • 一开始不使用std::for_each

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

于 2013-11-09T02:20:30.333 回答