Suppose you have a struct with elements which you don't want to (can't) initialize in the initialization phase, but is not default initializable.
I figured out a way of using std::launder:
Allocate a space for the structure, and then use the launder to assign a value at the right place. For example,
#include <cassert>
#include <cstddef>
#include <iostream>
#include <new>
struct T {
int t;
};
struct S {
int x;
T t;
S() = delete;
S(int x) : x(x) {}
};
int main() {
alignas(S) std::byte storage[sizeof(S)];
S s0(42);
// 0. I believe that the commented line is dangerous, although it compiles well.
// *std::launder(reinterpret_cast<S*>(storage)) = s0;
S *ps = std::launder(reinterpret_cast<S*>(storage));
ps->x = 42;
ps->t = T{};
{ // 1. Is this safe?
S &s1 = *ps;
std::cout << s1.x << std::endl;
s1.t.t = 24;
assert(s1.x == 42 && s1.t.t == 24);
}
{ // 2. Is this safe?
S s2 = *ps;
std::cout << s2.x << std::endl;
assert(s2.x == 42 && s2.t.t == 24);
}
{ // 3. Is this safe?
S s3 = std::move(*ps);
std::cout << s3.x << std::endl;
assert(s3.x == 42 && s3.t.t == 24);
}
}
The problem with this method is that it doesn't really 'construct' a structure, and therefore will not call a destructor.
- Is assigning a structure to a laundered object dangerous?
- Is referencing a laundered object safe?
- Is assigning another structure from a laundered object safe?
- Is moving a laundered object safe?
Thanks.
For
std::launderto have defined behavior there has to actually be an object of the given type at the location pointed to. That is not the case in this instance, so the behavior of your program is undefined.Consider if
S::twas astd::stringinstead of a simpleint. It would be completely uninitialized and so assigning to it would likely cause it to copy data into what it thinks is its storage buffer but is actually a random, un-owned location in memory.Simply put,
std::launderis the wrong tool for this job. You want placement-new: