6

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.

5
  • 4
    Does [language-lawyer] indicate you asking for a quote from the standard? If cppreference is good enough, a "view" is a lightweight object that indirectly represents iterable sequences, which must be copyable in constant time. Like std::string_view. Commented Aug 12 at 17:38
  • @DrewDormann I would prefer a quote, yes. Counterexample: std::ranges::owning_view stores a copy. Commented Aug 12 at 18:19
  • @DrewDormann But ignoring the language-laywering, are you saying that auto view = vec | a | b dangles whatever is returned by vec | a? Commented Aug 12 at 18:40
  • It does not -- it effectively creates a new view that "absorbs" vec | a. So it'll work. On that topic, std::ranges does some very clever things to catch "dangling" data that earlier stdlib functions would not. Dangling references become compiler errors. Commented Aug 12 at 18:50
  • @DrewDormann Ok, so you're saying that views get copied/moved, while anything else is stored by reference? If not a standard quote, do you know any documentation on this? Commented Aug 12 at 18:51

1 Answer 1

12

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

  • If the input is a view, it's copied or moved depending on the value category and never taken by reference.
  • If the input is not a view, it's moved (into an 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).

Sign up to request clarification or add additional context in comments.

1 Comment

The order of your two points are confusing, the 2nd one should have been stated before the first one, otherwise it's a generally ok answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.