【问题标题】:Is There a Standard Algorithm to Iterate Over a Range?是否有一个标准算法来迭代一个范围?
【发布时间】:2015-03-01 00:09:08
【问题描述】:

我需要在一个范围内调用每个 int 的 lambda。有没有标准算法可以做到这一点?

理想情况下是等效的:

for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);

【问题讨论】:

  • 是否使用 Boost 选项?
  • @Praetorian 我的意思是这可能是一个解决方案。不过,我希望 C++ 标准中有一些东西。
  • 运气好的话,范围很快就会成为标准,然后数字范围将由view::iota(13, 41)之类的东西表示
  • @JonathanMee,这是我所拥有的最好的,但我不确定是否有计划改变它:open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html。无论如何,作为一个答案,在 TS 被采用或接近那个点之前,我不会指望它是最有用的。
  • @JonathanMee,如果您对此感兴趣,可以在 Eric Niebler 的网站上找到更多信息。范围内容似乎真的开始围绕November, 2013。

标签: c++ algorithm for-loop range standard-library


【解决方案1】:

没有内置任何东西,没有。

您可以使用手工制作的迭代器和std::for_each 自己完成,或者使用Boost's counting iterators 来帮助您:

#include <boost/iterator/counting_iterator.hpp>
#include <algorithm>
#include <iostream>

int main()
{
    std::for_each(
        boost::counting_iterator<int>(13),
        boost::counting_iterator<int>(42),
        [](int i){ std::cout << i << ' '; }
    );
}

输出:

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

(live demo)

【讨论】:

    【解决方案2】:

    我不知道标准库中有什么东西可以按需生成您所要求的一系列数字。但这可以使用 Boost 以几种不同的方式完成。

    1. 使用Boost.Range生成一个整数范围,并与for_each的范围版本一起使用

      boost::for_each(boost::irange(13, 42), [](int i){ std::cout << i << ' '; });
      
    2. 使用来自 Boost.Iterator 的 boost::counting_iterator 并将其传递给 std::for_each

      std::for_each(boost::make_counting_iterator(13),
                    boost::make_counting_iterator(42), 
                    [](int i){ std::cout << i << ' '; });
      

    Live demo

    【讨论】:

      【解决方案3】:

      正如其他答案所提到的,如果 Boost 是一种选择,那么有更好的方法来做到这一点。如果没有,最好的方法是原始问题:

      for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);
      

      然而,未来是光明的,chris has mentioned 提案 N4128 建议将范围与迭代器一起纳入标准。

      现在草案仍处于早期状态,因此在确定如何使用之前需要进行大量澄清。但是其中一个概念是所有 STL 算法都将被重载以采用 views,这是一个瘦包装器,提供对所包含元素的访问,但也是一个智能结束位置。

      虽然选择了一个更复杂的示例来展示view 的强大功能,但作者在Motivation and Scope 中的示例使用了iota,这正是我们想要的:

      int total = accumulate(view::iota(1) |
                             view::transform([](int x){return x*x;}) |
                             view::take(10), 0);
      

      出于我们的目的,我们需要在 for_each 算法中使用 generate_n:

      for_each(view::generate_n(28,[]{static int i = 13; return i++;}),[](int i){/*do something*/});
      

      这将导致 generate_n 被调用 28 次 (13 + 28 = 41),创建的 view 将提供对这些数字的迭代,将它们输入到 for_each 中的原始 lambda。

      chris has suggested 代替 generate_n 修改 iota 可能会成功:iota(13, 41) 关键是要注意,无论使用什么都必须有一个结束条件,因为查看 懒惰 调用生成器,直到不再请求项目。所以这个 for_each(view::iota(10), [](int i){/*do something*/}); 定义了一个无限循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2012-11-05
        • 2011-07-21
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        相关资源
        最近更新 更多