+SG12 for UB / object model question.
[intro.object]/2 says:
> If an object is created in storage associated with a member subobject or array element /e/ (which may or may not be within its lifetime), the created object is a subobject of /e/'s containing object if:
> — the lifetime of /e/'s containing object has begun and not ended, and
> — the storage for the new object exactly overlays the storage location associated with /e/, and
> — the new object is of the same type as /e/ (ignoring cv-qualification).
Now, lets look at
struct S
{
std::byte m;
Let's imagine there's some more stuff here so sizeof(S) is larger:
char padding[123];
int align_to_int;
};
std::byte buf[sizeof(S)];
auto p = new (buf) S {}; //1
new (buf) std::byte{}; //2
If we continue this example:
int *p = new (buf + sizeof(int)) int;
... then we know at this point the lifetime of S has ended because its storage was reused. So if the object created at //2 was a subobject of the S object created at //1, then that object is in a bad state -- it's a subobject of an object whose lifetime has ended. That sounds problematic -- at least in principle -- for things that look like variant<S, std::byte>.
So I think either we want to say that the newly-created object at //2 is a subobject of two different objects or we want to say that we use angelic nondeterminism here (//2 either creates a subobject of S, replacing s.m, or creates a subobject of buf, replacing buf[0], depending on how the program continues). Given that we already have angelic nondeterminsm in the object model and don't otherwise have cases where the subobject structure is not a tree, I think the angelic nondeterminism model would likely be the better option. That and, I don't think it's desirable to allow a newly-created object to be used as two different subobjects -- the program should not be engaging in such object identity punning.