【问题标题】:Reuse nested loops without copy and paste无需复制和粘贴即可重用嵌套循环
【发布时间】:2011-08-23 09:01:08
【问题描述】:

假设我有这个嵌套循环

for (int a=1; a<MAX_A; ++a)
  for (int b=1; b<MAX_B; ++b)
    for (int c=1; c<MAX_C; ++c)
    {
       do_something(a, b ,c);
    }

我在代码的各个部分重用了这个循环,改变了函数do_something。每次前三行都重写很无聊。例如,在 python 中,我将创建一个生成器来返回一个迭代器 (1, 1, 1), (1, 1, 2), ... 或类似 itertools.product 的东西。

在 c++ 中,我想到的唯一解决方案是定义一个宏。更好的东西?e

【问题讨论】:

    标签: c++ loops macros foreach nested-loops


    【解决方案1】:

    使用模板:

    template<typename Func>
    inline void do_something_loop(Func f)
    {
        for (int a=1; a<MAX_A; ++a) 
          for (int b=1; b<MAX_B; ++b) 
            for (int c=1; c<MAX_C; ++c) 
            { 
               f(a, b ,c); 
            } 
    }
    

    可以使用任何匹配签名的函数指针或函数对象调用,例如:

    void do_something(int a, int b, int c) { /* stuff */ }
    
    do_something_loop(do_something);
    

    或者用函数对象:

    struct do_something
    {
        void operator()(int a, int b, int c) { /* stuff */ }
    };
    
    do_something_loop(do_something()); 
    

    或者,如果您的编译器支持 C++11,即使使用 lambda:

    do_something_loop([](int a, int b, int c) { /* stuff */ });
    

    请注意,您也可以将 f 参数声明为带有签名 void(*f)(int,int,int) 的函数指针,而不是使用模板,但这不太灵活(它不适用于函数对象(包括 std: :bind) 或 lambdas)。

    【讨论】:

    • 这个没问题,但是我每次都需要定义一个函数(没有c++11)。宏的优点是我可以写这样的东西:MYLOOP_BEGIN { v[a] = 10; vv[a][b][c] = a+1; } MYLOOP_END;
    • 是的,如果没有 lambda,除了宏之外别无他法。
    【解决方案2】:

    制作一个辅助循环函数:

    template<typename Work>
    void loop(Work work) {
      for (int a=1; a<MAX_A; ++a)
        for (int b=1; b<MAX_B; ++b)
          for (int c=1; c<MAX_C; ++c)
          {
            work(a, b ,c);
          }
    }
    

    定义要完成的工作:

    void some_work(int a, int b, int c) {
    }
    

    然后使用:

    loop(some_work);
    

    请注意,现在您不需要只使用函数,而是可以使用函数对象(operator() 重载的对象)。

    【讨论】:

    • 1/ do 是一个关键字(未测试代码的幽灵......) 2/ 在 C++ 中,some_work 之前的 &amp; 是不需要的,函数引用可以简单地转换为函数指针。
    猜你喜欢
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 2016-11-09
    • 2015-12-02
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    相关资源
    最近更新 更多