std::launder
Defined in header <new> | ||
|---|---|---|
template <class T> constexpr T* launder(T* p) noexcept; | (since C++17) (until C++20) | |
template <class T> [[nodiscard]] constexpr T* launder(T* p) noexcept; | (since C++20) |
Obtains a pointer to the object located at the address represented by p.
Formally, given.
- the pointer
prepresents the addressAof a byte in memory - an object
Xis located at the addressA -
Xis within its lifetime - the type of
Xis the same asT, ignoring cv-qualifiers at every level - every byte that would be reachable through the result is reachable through p (bytes are reachable through a pointer that points to an object
Yif those bytes are within the storage of an objectZthat is pointer-interconvertible withY, or within the immediately enclosing array of whichZis an element)
Then std::launder(p) returns a value of type T* that points to the object X. Otherwise, the behavior is undefined.
The program is ill-formed if T is a function type or (possibly cv-qualified) void.
std::launder may be used in a core constant expression if the value of its argument may be used in a core constant expression.
Notes
std::launder has no effect on its argument. Its return value must be used to access the object. Thus, it's always an error to discard the return value.
Typical uses of std::launder include:
- Obtaining a pointer to an object created in the storage of an existing object of the same type, where pointers to the old object cannot be reused because the object has
constor reference data members, or because either object is a base class subobject; - Obtaining a pointer to an object created by placement
newfrom a pointer to an object providing storage for that object.
The reachability restriction ensures that std::launder cannot be used to access bytes not accessible through the original pointer, thereby interfering with the compiler's escape analysis.
int x[10];
auto p = std::launder(reinterpret_cast<int(*)[10]>(&x[0])); // OK
int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0]));
// Undefined behavior: x2[1] would be reachable through the resulting pointer to x2[0]
// but is not reachable from the source
struct X { int a[10]; } x3, x4[2]; // standard layout; assume no padding
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x3.a[0])); // OK
auto p4 = std::launder(reinterpret_cast<int(*)[10]>(&x4[0].a[0]));
// Undefined behavior: x4[1] would be reachable through the resulting pointer to x4[0].a
// (which is pointer-interconvertible with x4[0]) but is not reachable from the source
struct Y { int a[10]; double y; } x5;
auto p5 = std::launder(reinterpret_cast<int(*)[10]>(&x5.a[0]));
// Undefined behavior: x5.y would be reachable through the resulting pointer to x5.a
// but is not reachable from the sourceExample
#include <new>
#include <cstddef>
#include <cassert>
struct X {
const int n; // note: X has a const member
int m;
};
struct Y {
int z;
};
struct A {
virtual int transmogrify();
};
struct B : A {
int transmogrify() override { new(this) A; return 2; }
};
int A::transmogrify() { new(this) B; return 1; }
static_assert(sizeof(B) == sizeof(A));
int main()
{
X *p = new X{3, 4};
const int a = p->n;
X* np = new (p) X{5, 6}; // p does not point to new object because X::n is const; np does
const int b = p->n; // undefined behavior
const int c = p->m; // undefined behavior (even though m is non-const, p can't be used)
const int d = std::launder(p)->n; // OK, std::launder(p) points to new object
const int e = np->n; // OK
alignas(Y) std::byte s[sizeof(Y)];
Y* q = new(&s) Y{2};
const int f = reinterpret_cast<Y*>(&s)->z; // Class member access is undefined behavior:
// reinterpret_cast<Y*>(&s) has value "pointer to s"
// and does not point to a Y object
const int g = q->z; // OK
const int h = std::launder(reinterpret_cast<Y*>(&s))->z; // OK
A i;
int n = i.transmogrify();
// int m = i.transmogrify(); // undefined behavior
int m = std::launder(&i)->transmogrify(); // OK
assert(m + n == 3);
}
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/utility/launder