I've read a few Q/A about std::launder
(What is the purpose of std::launder?, Does this really break strict-aliasing rules?, std::launder reachability rules), but am still unclear whether I am using it correctly in my specific use-case. The following is what I am trying to achieve:
struct Base {
...
};
struct Derived : Base {
...
};
// Declare a buffer
alignas(std::max_align_t) char buffer[2000];
// Populate the buffer using placement-new
*reinterpret_cast<size_t*>(&buffer[0]) = sizeof(Derived);
Derived *d = new (&buffer[2 * sizeof(std::max_align_t)]) Derived();
*reinterpret_cast<Base**>(&buffer[sizeof(std::max_align_t)]) = static_cast<Base*>(d);
// Extract values from the buffer
size_t s = *reinterpret_cast<size_t* >(&buffer[0]);
Base *b = *reinterpret_cast<Base** >(&buffer[sizeof(std::max_align_t)]);
d = *reinterpret_cast<Derived**>(&buffer[sizeof(std::max_align_t) * 2]);
My inclination is that the following is the appropriate way to std::launder
the above statements to ensure they all result in defined behavior per the standard:
// Populate the buffer using placement-new
*std::launder(reinterpret_cast<size_t*>(&buffer[0])) = sizeof(Derived);
Derived *d = new (&buffer[2 * sizeof(std::max_align_t)]) Derived();
*std::launder(reinterpret_cast<Base**>(&buffer[sizeof(std::max_align_t)])) = static_cast<Base*>(d);
// Extract values from the buffer
size_t s = *std::launder(reinterpret_cast<size_t* >(&buffer[0]));
Base *b = *std::launder(reinterpret_cast<Base** >(&buffer[sizeof(std::max_align_t)]));
d = *std::launder(reinterpret_cast<Derived**>(&buffer[sizeof(std::max_align_t) * 2]));
Is the above the appropriate usage of std::launder
? Do I have to placement-new the size_t
and Base*
members prior to assigning to them? Do I have to std::launder
the size_t
and Base*
members at all?