Date: Thu, 5 May 2022 17:34:01 +0200
Hi,
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,
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