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;

	  Provenance  fence  with  respect to p. Returns a pointer to the same
       memory that p
	  points to, but where the referent object is assumed to have  a  dis-
       tinct lifetime and
	  dynamic type.

	  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 <cassert>
	#include <cstddef>
	#include <new>

	struct Base
	{
	    virtual int	transmogrify();
	};

	struct Derived : Base
	{
	    int	transmogrify() override
	    {
		new(this) Base;
		return 2;
	    }
	};

	int Base::transmogrify()
	{
	    new(this) Derived;
	    return 1;
	}

	static_assert(sizeof(Derived) == sizeof(Base));

	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.
	    Base base;
	    int	n = base.transmogrify();
	    // int m = base.transmogrify(); // undefined behavior
	    int	m = std::launder(&base)->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.
	    struct Y { int z; };
	    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 ob-
       ject
	    const int g	= q->z;	// OK
	    const int h	= std::launder(reinterpret_cast<Y*>(&s))->z; //	OK

	    [](...){}(f, g, h);	// evokes [[maybe_unused]] effect
	}

	  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 did not consider
	  LWG		    2859	       C++17		       pointer
       included
			      arithmetic from pointer-interconvertible object
	  LWG 3495 C++17      std::launder might make pointer to  an  inactive
       forbidden
			      member dereferenceable in	constant expression

http://cppreference.com		  2024.06.10		       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.1.quarterly>

home | help