C++20 std::ranges:跳过每个第N个元素的范围适配器

5

我正在尝试更熟悉C++20的std::ranges实现,在此过程中,我遇到一个看似简单的问题,即在不自己实现的情况下找不到标准解决方案。

问题很简单:我想使用C++20范围适配器仅访问和处理范围内每N个元素。例如,我正在寻找以下内容的工具:

for (auto x : std::ranges::iota_view{0, 10} | std::ranges::<some api>(3)) {
    std::cout << x << " ";
}

会产生以下输出结果:
0 3 6 9

当然可以使用像 std::ranges::filter 这样的工具来实现过滤,但是 filter 实际上会访问和处理迭代器中每个值,例如它会计算表达式 "predicate(*it)"。对于简单小型范围这是可以接受的,但是对于更复杂/昂贵的生成器迭代器,计算 *it 可能会很昂贵且不希望使用这些值。

我正在寻找更相似于 std::ranges::take 或者 std::ranges::drop 的行为,只是通过迭代跳过该值,而不是访问它。

是否有一个简单的 C++20 方案可以实现这一点?或者我必须使用包装器迭代器/标志来自己编写代码,在其中执行 operator++ 操作 N 次?这听起来像是一个应该已经成为标准一部分的实用程序,但我似乎找不到符合这个描述的任何内容。

1个回答

7
我认为标准库中没有适用于此的范围适配器。
然而Ranges-v3库中有这个适配器。
ranges::iota_view{0, 10} | ranges::stride_view(3)

有一个提案要将这样的适配器加入标准:P1899。 Github Issue 表示:

在布拉格由LEWG进行了讨论。 http://wiki.edg.com/bin/view/Wg21prague/P1899

确保步长为正,一致同意。

修改(注意事项中有很多建议)并退回LEWG。一致同意。

我没有找到笔记的公共副本。
还有另一个提案要向iota_view添加步骤参数,以在示例情况下实现相同的功能:P2016

谢谢您的答复!看起来我必须研究一下使用或采用Ranges-V3中的实现。很奇怪这个看似简单的API在标准中被省略了,因为没有一个可比较的等效方法来完成相同的任务。 - Human-Compiler
1
@Human-Compiler 标准范围中有一些小而有用的部分被省略了。据我所知,这是为了使原始提案更小,从而更容易、更快速地评估、接受和实现。假设链接的提案与ranges-v3相同,并考虑到有许多建议,这样的修订可能会延迟C++20之后的范围。 - eerorika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接