On Sun, 22 Jan 2023 at 08:32, Thiago Macieira via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Saturday, 21 January 2023 06:20:25 PST Edward Catmur via Std-Proposals
wrote:
> Right. The existence of that unary array is somewhat questionable, since it
> would not be possible to create such an array within the program. That
> aside, you are correct which means that the UB occurs in the next
> iteration, when the past the end iterator is indirected.

Which points to a valid use-case of sizeof in an abstract class and pointer
math with it.

template <typename It, typename L> void apply(It begin, It end, L lambda)
{
   for ( ; begin <= end; ++begin)
        lambda(*begin);
}

void f(I *ptr)
{
    apply(ptr, ptr+1, [](auto p) { p->something(); });
}

That only uses pointer arithmetic, not `sizeof`?

I'm not saying this is good code, but it's perfectly valid. I know I've used 
the "any object is an array of 1" technique.

https://gitlab.com/thiagomacieira/qtbase/-/blob/master/src/corelib/tools/
qgenericarray.h#L310-313

(this code is not in production, it was a prototype)

 You aren't going to be able to create a QGenericArray of abstract class `I`, though?

I feel like we should be moving away from 1-element array views now we have iterator-sentinel pairs (e.g. for std::views::single). I guess you might want to erase down to a pointer pair, though.

Also, there's the possibility you might want to inspect the memory of an abstract base class, e.g. as_bytes(span(static_cast<I*>(&obj), 1)). You need either sizeof or pointer arithmetic to do that, so I don't think we can talk about making them ill-formed.

Still, a warning flag would be good to experiment with: -Wabstract-sizeof, -Wabstract-pointer-arithmetic.