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.
The general rules are (which are the same as all
's rules):
owning_view
) if an rvalue, and a reference is taken if an lvalue.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).