Date: Thu, 6 Jul 2023 20:21:33 +0200
On Thu, Jul 6, 2023 at 6:37 PM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:
> Consider the following modification of your example:
>
> class Element;
> *struct* Storage {
> ...
> *const vector<Element>&* get_elements();
> };
> extern void process(span<Element>);
> void do_something(Storage& storage) {
> process(storage.get_elements()); // ill-formed
> }
>
> Can I make a `span<Element>` out of a `const vector<Element>&`? Nope, I
> can't.
> Why not? Because `span<Element>`'s constructor requires a contiguous range
> of Elements, and `vector<Element>` doesn't satisfy `contiguous_range`.
> And why doesn't it? Because its iterator type is `Element*`, and that is
> not a contiguous iterator.
> Why not? Because it's not any kind of iterator. It's not even
> weakly_incrementable. `Element *p; ++p;` is ill-formed (when `Element` is
> incomplete).
>
First of all, there is a small mistake, it should be `span<const Element>`
or `vector<Element>&` (without 'const') in your example, but I get your
idea.
This is true that by now it's no longer possible to make `span<Element>`
constructible from`vector<Element>&`. And this is bad from my POV.
But your signature of `Storage::get_elements()` simply means that the
author has no desire to allow users of `Storage::get_elements()` to iterate
through elements, if 'Element' is incomplete, otherwise he has a lot of
ways to fix it (the dumbest one is to return `pair<Element const*, size_t>`
instead of `vector<Element>&`.
> This doesn't at all kill your proposal; but you must address it head-on in
> your paper.
> Particularly, you must try implementing this, and give an (empirically
> tested) table of examples that Just Work after your patch, versus those
> that Don't Work.
> For example, presumably this would make `span<Element>`
> copy-constructible, right?
>
Yes, it should be copy-constructible, even more *trivially* copy-constructible
and in general trivially copyable, this requirement already exists (
https://eel.is/c++draft/views.span#span.overview-3), and I see no reason to
relax it for incomplete element type.
But would it also make `span<Element, 42>` convertible to `span<Element>`?
> or would that still Not Work, because of the logic above?
>
We know it would *not* make `vector<Element>` convertible to
> `span<Element>`.
>
Despite the unfortunate fact that `vector<Element>` couldn't be made
convertible to `span<Element>`, because `vector` could store `__begin`,
`__end` pointers instead of `__data` and `__size` fields, I see no reason
why not to make `span<Element, 42>` convertible to `span<Element>`.
We should just add a separate converting constructor (or conversion
operator) rather than rely on the generic constructor from contiguous range
(https://eel.is/c++draft/views.span#lib:span,constructor____).
wrote:
> Consider the following modification of your example:
>
> class Element;
> *struct* Storage {
> ...
> *const vector<Element>&* get_elements();
> };
> extern void process(span<Element>);
> void do_something(Storage& storage) {
> process(storage.get_elements()); // ill-formed
> }
>
> Can I make a `span<Element>` out of a `const vector<Element>&`? Nope, I
> can't.
> Why not? Because `span<Element>`'s constructor requires a contiguous range
> of Elements, and `vector<Element>` doesn't satisfy `contiguous_range`.
> And why doesn't it? Because its iterator type is `Element*`, and that is
> not a contiguous iterator.
> Why not? Because it's not any kind of iterator. It's not even
> weakly_incrementable. `Element *p; ++p;` is ill-formed (when `Element` is
> incomplete).
>
First of all, there is a small mistake, it should be `span<const Element>`
or `vector<Element>&` (without 'const') in your example, but I get your
idea.
This is true that by now it's no longer possible to make `span<Element>`
constructible from`vector<Element>&`. And this is bad from my POV.
But your signature of `Storage::get_elements()` simply means that the
author has no desire to allow users of `Storage::get_elements()` to iterate
through elements, if 'Element' is incomplete, otherwise he has a lot of
ways to fix it (the dumbest one is to return `pair<Element const*, size_t>`
instead of `vector<Element>&`.
> This doesn't at all kill your proposal; but you must address it head-on in
> your paper.
> Particularly, you must try implementing this, and give an (empirically
> tested) table of examples that Just Work after your patch, versus those
> that Don't Work.
> For example, presumably this would make `span<Element>`
> copy-constructible, right?
>
Yes, it should be copy-constructible, even more *trivially* copy-constructible
and in general trivially copyable, this requirement already exists (
https://eel.is/c++draft/views.span#span.overview-3), and I see no reason to
relax it for incomplete element type.
But would it also make `span<Element, 42>` convertible to `span<Element>`?
> or would that still Not Work, because of the logic above?
>
We know it would *not* make `vector<Element>` convertible to
> `span<Element>`.
>
Despite the unfortunate fact that `vector<Element>` couldn't be made
convertible to `span<Element>`, because `vector` could store `__begin`,
`__end` pointers instead of `__data` and `__size` fields, I see no reason
why not to make `span<Element, 42>` convertible to `span<Element>`.
We should just add a separate converting constructor (or conversion
operator) rather than rely on the generic constructor from contiguous range
(https://eel.is/c++draft/views.span#lib:span,constructor____).
-- Andrey Davydov
Received on 2023-07-06 18:21:46