5

I'm trying to get more acquainted with C++20's std::ranges implementation, and I've come across a seemingly simple problem of which I cannot find a standard solution without rolling my own implementation.

The problem is simple: I would like to only access and process every Nth element in a range using a C++20 range-adapter. For example, I'm looking for a utility where the following:

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

will produce an output like:

0 3 6 9

This can of-course be accomplished with something like std::ranges::filter -- however filter actually accesses and processes the iterator at each value, e.g. it evaluates the expression "predicate(*it)". For small simple ranges this is fine, but for more complex/expensive generator iterators, then evaluating *it can be costly and undesirable since these values will be otherwise unused.

I'm looking for something more equivalent to the behavior of std::ranges::take or std::ranges::drop, which simply bypass the value by iterating over it, rather than accessing it.

Is there a simple, C++20 solution to accomplish this? Or will I have to roll my own with a wrapper iterator/sentinel where operator++ is done N times? This sounds like a utility that should already be part of the standard, but I can't seem to find anything fitting this description.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Human-Compiler
  • 11,022
  • 1
  • 32
  • 59

1 Answers1

7

I don't think there is a range adaptor for this in the standard library.

Ranges-v3 library does however have it:

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

There is a proposal to add such adaptor into the standard: P1899.

Github Issue says:

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

I didn't find public copy of the notes.


There is also another proposal to add step parameter to iota_view that would achieve the same for the example case: P2016.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thanks for the answer! Looks like I'll have to look into either using or adopting the implementation from Ranges-V3. It's strange that this seemingly simple API has been omitted from the standard when there isn't really a comparable equivalent to accomplish the same task. – Human-Compiler Jun 29 '21 at 05:19
  • 1
    @Human-Compiler There are several little useful bits left out of the standard ranges. To my understanding, it was to keep the original proposal smaller and thus easier and faster to evaluate, accept and implement. Assuming the linked proposal is identical to ranges-v3, and considering there were many suggestions, such revisioning would presumably would have delayed ranges beyond C++20. – eerorika Jun 29 '21 at 05:30