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.