Consider the following.
struct T { int a = 1; };
struct U { char b = 2; };
static_assert(alignof(U) == 1);
// Allocate storage. Cast via P0593 to access implicit array of unsigned char.
auto* s = reinterpret_cast<unsigned char*>(::operator new(sizeof(T) + sizeof(U)));
// Place T and U in that storage.
T* t = new (s) T;
U* u = new (s + sizeof(T)) U;
// Is there a legal way to get a pointer to `u` given only `t` and not `s`?
U* u2 = reinterpret_cast<U*>(reinterpret_cast<unsigned char*>(t) + sizeof(T));
The question: Is there a way, given only t
to get u
?
I know I can std::launder()
s
to get t
, and presumably I can std::launder()
s + sizeof(T)
to get u
. But, if all I have is t
, is there a way?
I know that std::launder()
has requirements about "reachability", so I don't think it can be part of the solution since u
is not reachable from t
.
I know that if I put T and U together in a struct, things are different, but that's not the case I am interested in. (Consider that U might actually be of dynamic size.)
I think my question boils down to: How do I recover s
(the underlying complete storage) from t
? I know I can get the object representation of the object at t
, but I don't think that's the same as s
because it's only sizeof(T)
long, right?
If I want to allocate once and store these non-array disparate objects, am I forced to store a pointer to u
inside t
just to recover it later?
As you are saying std::launder
has a precondition that explicit prohibits this. It seems intended to be impossible.
There are a few other constructs in the language that can make more bytes reachable than should be possible by this precondition, see e.g. my questions std::launder vs placement-new reachability condition and Does implicit object creation circumvent reachability conditions of std::launder?.
However, given that these restrictions were explicitly added to std::launder
, I suspect that them not being applied to these other constructs as well is the defect and not the other way around.
I do not know whether there is any compiler that actually makes use of this reachability restriction for optimization though.