I've just read
What is the purpose of std::launder?
and frankly, I am left scratching my head.
Let's start with the second example in @NicolBolas' accepted answer:
aligned_storage<sizeof(int), alignof(int)>::type data; new(&data) int; int *p = std::launder(reinterpret_cast<int*>(&data));
[basic.life]/8 tells us that, if you allocate a new object in the storage of the old one, you cannot access the new object through pointers to the old.
std::launder
allows us to side-step that.
So, why not just change the language standard so that accessing data
through a reinterpret_cast<int*>(&data)
is valid/appropriate? In real life, money laundering is a way to hide reality from the law. But we don't have anything to hide - we're doing something perfectly legitimate here. So why can't the compiler just change it's behavior to its std::launder()
behavior when it notices we're accessing data
this way?
On to the first example:
X *p = new (&u.x) X {2};
Because X is trivial, we need not destroy the old object before creating a new one in its place, so this is perfectly legal code. The new object will have its n member be 2.
So tell me... what will
u.x.n
return?The obvious answer will be 2. But that's wrong, because the compiler is allowed to assume that a truly
const
variable (not merely a const&, but an object variable declaredconst
) will never change. But we just changed it.
So why not make the compiler not be allowed to make the assumption when we write this kind of code, accessing the constant field through the pointer?
Why is it reasonable to have this pseudo-function for punching a hole in formal language semantics, rather than setting the semantics to what they need to be depending on whether or not the code does something like in these examples?