Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::launder(3)		      C++ Standard Libary	       std::launder(3)

NAME
       std::launder - std::launder

Synopsis
	  Defined in header <new>
	  template <class T>				      (since C++17)
	  constexpr T* launder(T* p) noexcept;		      (until C++20)
	  template <class T>				      (since C++20)
	  [[nodiscard]]	constexpr T* launder(T*	p) noexcept;

	  Obtains  a  pointer to the object located at the address represented
       by p.

	  Formally, given

	    * the pointer p represents the address A of	a byte in memory
	    * an object	X is located at	the address A
	    * X	is within its lifetime
	    * the type of X is the same	as T, ignoring cv-qualifiers at	 every
       level
	    *  every byte that would be	reachable through the result is	reach-
       able through p
	      (bytes are reachable through a pointer that points to an	object
       Y if those bytes
	      are  within the storage of an object Z that is pointer-intercon-
       vertible	with Y,
	      or within	the immediately	enclosing array	of which Z is an  ele-
       ment).

	  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	 func-
       tion 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:

	    *  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
       (for instance,
	      because either object is a base class subobject);
	    * Obtaining	a pointer to an	object created by placement new	from 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 interfer-
       ing 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
       // Run this code

	#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 be-
       cause 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:
						     //		      reinter-
       pret_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 retroac-
       tively to
	  previously published C++ standards.

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

http://cppreference.com		  2022.07.31		       std::launder(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::launder&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help