From 67e722e9588f5df28bcbccc81bddbd75bd2e7604 Mon Sep 17 00:00:00 2001 From: AgustinAl Date: Tue, 26 Jul 2022 18:26:13 -0700 Subject: [PATCH] fixes issue #1608 --- public/docs/cpp/utility/launder.html | 91 ++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 public/docs/cpp/utility/launder.html diff --git a/public/docs/cpp/utility/launder.html b/public/docs/cpp/utility/launder.html new file mode 100644 index 00000000..3b838a9e --- /dev/null +++ b/public/docs/cpp/utility/launder.html @@ -0,0 +1,91 @@ +

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

+

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 and only if the (converted) value of its argument may be used in place of the function invocation. In other words, std::launder does not relax restrictions in constant evaluation.

+

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:

+

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 source

Example

#include <new>
+#include <cstddef>
+#include <cassert>
+ 
+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()
+{
+  // Case 1: the new object failed to be transparently replaceable because it is a
+  // base subobject but the old object is a complete object.
+  A i;
+  int n = i.transmogrify();
+  // int m = i.transmogrify(); // undefined behavior
+  int m = std::launder(&i)->transmogrify(); // OK
+  assert(m + n == 3);
+ 
+  // Case 2: access to a new object whose storage is provided by a byte array through
+  // a pointer to the array.
+  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
+ 
+  [f, g, h] {}; // suppresses "unused-variable" warnings; see also [[maybe_unused]].
+}

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

+ + + + +
DR Applied to Behavior as published Correct behavior
LWG 2859 C++17 definition of reachable didn't consider pointer-arithmetic from pointer-interconvertible object included
LWG 3495 C++17 launder might make pointer to an inactive member dereferenceable in constant expression forbidden
+

+ © cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
+ https://en.cppreference.com/w/cpp/utility/launder +

+