std::launder
From cppreference.com
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
p
represents the addressA
of a byte in memory - an object
X
is located at the addressA
-
X
is within its lifetime - the type of
X
is 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
Y
if those bytes are within the storage of an objectZ
that is pointer-interconvertible withY
, or within the immediately enclosing array of whichZ
is 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
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 the object has
const
or reference data members and so pointers to the old object cannot be reused; - Obtaining a pointer to an object created by placement
new
from a pointer to an object providing storage for that object.
Example
Run this code
#include <new> #include <cstddef> struct X { const int n; // note: X has a const member int m; }; struct Y { int z; }; int main() { X *p = new X{3, 4}; const int a = p->n; new (p) X{5, 6}; // p does not point to new object because X::n is const const int b = p->n; // undefined behavior const int x = p->m; // undefined behavior (even though m is non-const, p can't be used) const int c = std::launder(p)->n; // OK, std::launder(p) points to new object alignas(Y) std::byte s[sizeof(Y)]; Y* q = new(&s) Y{2}; const int d = 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 e = q->z; // OK const int f = std::launder(reinterpret_cast<Y*>(&s))->z; // OK }