C++ Logo


Advanced search

What satisfies std::ranges::view after P2415?

From: Giuseppe D'Angelo <giuseppe.dangelo_at_[hidden]>
Date: Thu, 5 May 2022 17:34:01 +0200

P2415 changes the semantic requirements for `std::ranges::view` in some
ways that I'm having some trouble understanding.

https://eel.is/c++draft/range.view now says that T models view only if:

> (1) T has O(1) move construction; and
> (2) move assignment of an object of type T is no more complex than destruction followed by move construction; and
> (3) if N copies and/or moves are made from an object of type T that contained M elements, then those N objects have O(N+M) destruction; and
> (4) copy_­constructible<T> is false, or T has O(1) copy construction; and
> (5) copyable<T> is false, or copy assignment of an object of type T is no more complex than destruction followed by copy construction.

Based on this, I'd claim that:

* a non-COW string class is not a view (violates 4);

* a COW string class *is* a view;

* a COW+SSO string class *is* a view.

But then lines start to blur a bit:

* a COW container of arbitrary objects is a view? I'd say yes. This is
pretty close to the shared_ptr example (§4.2 in [range.view]);

* a std::vector<copyable type> is NOT a view (violates 3, 4);

* ... but a std::vector<std::unique_ptr<int>> *is* a view? (In general,
a container over move-only types is a view?)

* Similarly, a std::array<int, 100'000> is a view...? It has O(1) copies
and moves.

Am I misunderstanding something so far? Is the above OK according to the
letter of the law?

The paper concludes its exposition with:

> There may not be a clean answer, which is admittedly unsatisfying, but it mainly boils down to:
> auto rng = v | views::reverse;
> If v is an lvalue, do you want rng to copy v or to refer to v? If you want it to copy v, because copying v is cheap and you want to avoid paying for indirection and potentional dangling, then v is a view.

I think my problem is that the "copying v is cheap" part isn't quite
captured by the concepts; they just say that copy has to be O(1), and
that applies to things like array<T, 100'000>. The distinction around
being cheap or not cheap isn't quite clear-cut to me, and certainly
hinders generic programming (should one mark array<T, N> as a view only
up to certain values of N? Does that make any sense?)

Thank you for any insight,
Giuseppe D'Angelo

Received on 2022-05-05 15:34:05