是否有一个标准算法来迭代一个范围?
Is There a Standard Algorithm to Iterate Over a Range?
我需要对范围内的每个 int
调用一个 lambda。是否有执行此操作的标准算法?
理想情况下是等价物:
for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);
没有什么内置的,没有。
您可以使用手工制作的迭代器和 std::for_each
, or use 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)
我不知道标准库中有什么可以像您要求的那样按需生成一系列数字。但这可以使用 Boost 以多种不同的方式完成。
使用Boost.Range生成整数范围,并与for_each
的范围版本一起使用
boost::for_each(boost::irange(13, 42), [](int i){ std::cout << i << ' '; });
使用 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 << ' '; });
正如其他答案所提到的,如果 Boost 是一个选项,那么有更好的方法来做到这一点。如果没有,最好的办法在原题中:
for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);
然而,未来是光明的, proposal N4128 建议将范围与迭代器一起纳入标准。
现在草案仍处于早期阶段,因此在确定如何使用它之前需要进行大量澄清。但其中一个概念是,所有 STL 算法都将被重载以采用 view
s,这是一个薄包装器,提供对包含元素的访问,但也是一个智能结束位置。
虽然是一个更复杂的例子,为了展示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
.
而不是 generate_n
对 iota
的修改可能会达到目的:iota(13, 41)
关键是要注意无论使用什么都必须有一个结束条件,因为视图 lazily 调用生成器,直到不再请求任何项目。所以这个for_each(view::iota(10), [](int i){/*do something*/});
定义了一个无限循环。
我需要对范围内的每个 int
调用一个 lambda。是否有执行此操作的标准算法?
理想情况下是等价物:
for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);
没有什么内置的,没有。
您可以使用手工制作的迭代器和 std::for_each
, or use 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)
我不知道标准库中有什么可以像您要求的那样按需生成一系列数字。但这可以使用 Boost 以多种不同的方式完成。
使用Boost.Range生成整数范围,并与
的范围版本一起使用for_each
boost::for_each(boost::irange(13, 42), [](int i){ std::cout << i << ' '; });
使用 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 << ' '; });
正如其他答案所提到的,如果 Boost 是一个选项,那么有更好的方法来做到这一点。如果没有,最好的办法在原题中:
for(auto i = 13; i < 42; ++i)[](int i){/*do something*/}(i);
然而,未来是光明的,
现在草案仍处于早期阶段,因此在确定如何使用它之前需要进行大量澄清。但其中一个概念是,所有 STL 算法都将被重载以采用 view
s,这是一个薄包装器,提供对包含元素的访问,但也是一个智能结束位置。
虽然是一个更复杂的例子,为了展示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
.
generate_n
对 iota
的修改可能会达到目的:iota(13, 41)
关键是要注意无论使用什么都必须有一个结束条件,因为视图 lazily 调用生成器,直到不再请求任何项目。所以这个定义了一个无限循环。for_each(view::iota(10), [](int i){/*do something*/});