【问题标题】:c++ repeat N iterationsc ++重复N次迭代
【发布时间】:2019-02-28 11:40:50
【问题描述】:

我可以清楚地做这样的事情:

for(int i = 0; i < 10000; i++)
    testIteration();

但是有没有任何标准函数可以在一行中做类似的事情?类似的东西:

std::repeat(10000, testIteration);

【问题讨论】:

  • 在 C++11 中?不,什么都没有。我应该可以用C++20 rangesstd::for_each 做点什么。在 C++20 可用且通用之前,您可以使用 the ranges library,它是 C++20 范围的基础。
  • 如果您使用循环将某些操作应用于容器的每个元素,那么有标准算法。但是,本质上重复一个函数调用任意次数......这就是循环构造的用途,标准库很少尝试复制使用语言特性更容易完成的事情。如果您真的想要这样的功能,请自行推出 - 只是不要尝试将其放入命名空间 std(因为这样做会产生未定义的行为)。
  • 新的 std::for_each 甚至新的 for 语法都有助于减少经常需要的样板文件。但是,根据经验,它实际上会导致更多样板。考虑您希望调用的函数是类的成员函数的情况;不能像这里一样简单地传递函数指针。
  • 在这种情况下,IMO 您极不可能在可读性方面超越该循环。
  • 好吧,1/ 你真的应该为此使用循环; 2/ 有std::for_each_n 但它没有在gcc 和clang 中实现; 3/ C++20 范围可能是一个解决方案; 4/ 提醒 1/.

标签: c++ c++11


【解决方案1】:

proposed standard for C++20 中有一个iota_view 的示例:

for (int i : iota_view{1, 10})
  cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9

但目前,range-v3 库可以使用:

for (int _ : view::iota{0, 10})
    testIteration();            // calls testIteration 10 times.

【讨论】:

    【解决方案2】:

    但是是否有任何 std 函数可以在一行中执行类似的操作?

    不,标准库中没有算法可以做到这一点(至少没有什么不需要编写无用的样板)。正如其他人已经提到的那样,循环是 n 次做“某事”的最易读、最不容易混淆的方式。

    话虽如此,如果你把它当作一个练习来获得更简洁的语法,你可以这样写:

    #include <iostream>
    struct my_counter {    
        int stop;
        struct iterator {
            int count;    
            iterator& operator++() { ++count; return *this; }
            int operator*() { return count;}
            bool operator!=(const iterator& other) { return count != other.count; }
        };
        iterator begin() { return {0}; }
        iterator end() { return {stop};}    
    };
    
    void print() { std::cout << "x"; }
    
    int main() {
         for (auto x : my_counter{5}) print();
    }
    

    但是,我强烈建议不要使用类似的东西。每个人都知道循环是如何工作的以及它的作用。习惯了 for 循环,您可以在眨眼间阅读 for 循环,而其他任何事情都是不常见的、令人惊讶和令人困惑的,除非当然有标准算法(尽管我怀疑这种特殊情况的算法是否会有很大用处) .既然可以使用循环,为什么还要重新发明轮子?

    【讨论】:

    • 为什么?并行!
    • @DavidHParry 为什么?对不起,不知道你指的是什么
    • 您明确地问过“......既然可以使用循环,为什么还要重新发明轮子?”我回答了你。
    • @DavidHParry 这个答案怎么样?它解释得一样多。为什么?意大利面条! :P。说真的,我看不出一个在并行性方面比另一个更好
    • 去看看std::execution::*和C++中的STD库的关系。不客气。
    【解决方案3】:

    我个人喜欢使用一个小的辅助函数来做到这一点。

    template <typename F>
    void repeat(size_t n, F f) {
      while (n--) f();
    }
    
    int main() {
    
       repeat(1000, [&] {
          testIteration();
       });
    }
    

    这避免了必须拼出变量的名称。不过,当我需要名称时,我更喜欢使用 view::iota。

    话虽如此,有人告诉我这读起来很混乱,而且每个人都可以阅读 for 循环,所以这可能是要走的路。 (当然,除非函数放在 std:: 中)。

    【讨论】:

      【解决方案4】:

      仅供参考,可以使用std::generatestd::generate_n,但只能通过执行以下操作来初始化数组:

      int i = 0;
      std::generate_n(myArray, 10000, [&]() -> int { return i++; });
      

      【讨论】:

        【解决方案5】:

        我知道这并没有提供上述答案中的任何新内容,只是我的解决方案可能非常短。要重复代码 2 次,我使用如下循环:

        for (auto _ = 2; _--;) { /* this code gets repeated twice */ }
        

        我认为使用前缀运算符会不太清楚,因为重复代码两次循环需要:

        for (auto _ = 3; --_;) { /* this code gets repeated twice */ }
        

        【讨论】:

          【解决方案6】:

          简单地定义一个宏怎么样? #define FOR(N, foo, ...) for (int _i = 0; _i &lt; N; _i++) foo(__VA_ARGS__);

          例如。

          #include <iostream>
          
          #define FOR(N, foo, ...) for (int _i = 0; _i < N; _i++) foo(__VA_ARGS__);
          
          void bar(int a, int b)
          {
              std::cout << "hello " << a+b << std::endl;
          }
          
          int main()
          {
              FOR(5, bar, 12, 6);
              return 0;
          }
          

          输出:

          hello 18
          hello 18
          hello 18
          hello 18
          hello 18
          

          【讨论】:

          • 没有。只是……不。
          猜你喜欢
          • 2013-09-21
          • 1970-01-01
          • 2016-05-30
          • 2018-04-04
          • 2014-02-12
          • 2016-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多