c++language-lawyerstd-ranges

Do C++20 `std::views` store copies or references to their input ranges?


C++20 adds numerous std::views::... range adaptors.

When applied to a range, do they store a copy of the range, or a reference to it?

In other words:

std::vector<A> v;
for (const auto &elem : v | std::views::reverse) {}

Does this copy the vector, or stores a reference to it?

And if the range is an rvalue, does that affect the behavior?


I'm asking about the bulk of the views in std::views, as I assume most of them share the same behavior.

Some views appear to be special-cased on this, e.g. std::views::all is said to store references to lvalues but move rvalues. It's not clear to me if the remaining views do the same thing, or do something else?


I found some related wording in RangeAdaptorClosureObject, but that deals with combining adaptors together (which copies/moves the adaptors being combined), not applying an adaptor to a range.

I tried passing a vector of a non-copyable type to std::views::reverse and didn't get an error, so I assume at least lvalues are not copied, but I can't find where this is specified.


Solution

  • The general rules are (which are the same as all's rules):

    For most unary adaptors, this is done by using views::all_t directly in the spec (example). For the rest, they are specified to use CTAD (example), and the applicable deduction guide will use views::all_t on the source range (example).