On Thu, Jul 6, 2023 at 6:37 PM Arthur O'Dwyer <arthur.j.odwyer@gmail.com> 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