Brian Bi
Brian Bi

Reputation: 119467

How to interpret the reachability requirement of std::launder?

The std::launder function requires that every byte that would be reachable through the result is reachable through the argument. "Reachable" is defined as follows:

A byte of storage is reachable through a pointer value that points to an object Y if it is within the storage occupied by Y, an object that is pointer-interconvertible with Y, or the immediately-enclosing array object if Y is an array element.

According to an answer to another question, this restriction "... means that you cannot use launder to obtain a pointer that would allow you to access more bytes than the source pointer value allows, on pain of undefined behavior."

This makes sense for the examples given by T.C. but I don't understand how to interpret it in the case where the original object has been replaced by a new object, which is the original purpose contemplated for std::launder. The standard has the following example:

struct X { const int n; };
X *p = new X{3};
const int a = p->n;
new (p) X{5}; // p does not point to new object (6.8) because X::n is const
const int b = p->n; // undefined behavior
const int c = std::launder(p)->n; // OK

In this case, by the time std::launder is called, the object pointed to by p---the original X object---has already ceased to exist since the creation of a new object in the storage it occupied has implicitly ended its lifetime ([basic.life]/1.4). Therefore, it seems that there are no bytes reachable through p since p does not point to any object Y. This is obviously not the intended reading since it would make the call to std::launder undefined behaviour in the example.

  1. Have I misunderstood the wording here, or is the wording defective?
  2. What is the intended meaning, which would make the example valid?

Upvotes: 17

Views: 446

Answers (1)

darune
darune

Reputation: 11022

Just going by the example, the relevant text is (Bold is mine):

A byte of storage is reachable through a pointer value that points to an object Y if it is within the storage occupied by Y

Due to the placement new, the pointer value now points to the "newly placed" object, and hence the reachability is of that.

I would say that is clear enough as it stands.

Upvotes: 1

Related Questions