Basic.life/8 tells us that we can use the storage occupied by an object to create a new one after its lifetime has ended and use its original name to refer to it unless:
- the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and [...]
emphasis mine
But, just below that we can see a note saying that:
- If these conditions are not met, a pointer to the new object can be obtained from a pointer that represents the address of its storage by calling
std::launder
This explains the purposes of std::launder
. We can have a class type that has const
members and use placement-new to create a new object there with different internal values.
What surprises me is the first part of the first quote. It clearly indicates that if the storage is const
(not necessarily contains const
members, but the whole object is declared as const
), we cannot use it to refer to a new object as is, but it may imply that std::launder
may fix it.
But how would we create such object? The simplest example fails:
const auto x = 5;
new (&x) auto(10);
It's because we cannot use const void*
as a buffer for placement-new. We could const_cast
it, but casting away a "true" const
ness is Undefined Behaviour. I believe this is also the case here.
I would understand if there simply was a prohibition of using const
objects as placement-new buffer, but if that would be the case, what would be the purpose of the emphasised part of the first quote? Can we use reuse a truly const
object's storage for a different object?