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

C++20 std::ranges: Range adapter to skip every nth element

我试图更熟悉 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)”。对于小的简单范围,这很好,但是对于更多的 complex/expensive 生成器迭代器,那么评估 *it 可能代价高昂且不受欢迎,因为这些值将不会被使用。

我正在寻找与 std::ranges::take or std::ranges::drop 的行为更等效的东西,它只是通过遍历它来绕过值,而不是访问它。

是否有一个简单的 C++20 解决方案来完成此任务?或者我是否必须使用包装器 iterator/sentinel 自己滚动,其中 operator++ 已完成 N 次?这听起来像是一个应该已经成为标准一部分的实用程序,但我似乎找不到任何符合此描述的内容。

我认为标准库中没有适用于此的范围适配器。

Ranges-v3 图书馆确实有它:

ranges::iota_view{0, 10} | ranges::stride_view(3)

有人提议将这样的适配器添加到标准中:P1899

Github Issue 说:

Discussed by LEWG in Prague. http://wiki.edg.com/bin/view/Wg21prague/P1899

Ensure that stride is positive. Unanimous consent

Revise (many suggestions in the notes) and return to LEWG. Unanimous consent

我没有找到笔记的 public 副本。


还有另一个建议将步骤参数添加到 iota_view,这将在示例案例中实现相同的效果:P2016.