17

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?
TrebledJ
  • 8,713
  • 7
  • 26
  • 48
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 5
    "Points to an out-of-lifetime object" != "doesn't point to an object". – T.C. Aug 12 '19 at 17:53
  • I think that key part is `within the storage occupied by Y`. So even if lifetime ended, storage is available, and a pointer can point to it (pointer value doesn't become invalid pointer value). – geza Aug 12 '19 at 17:54
  • @T.C. If your answer is that objects are still considered to exist in storage after their lifetime has ended, you should post that as an answer. I can't figure out what stance the C++17 standard adopts on this---it seems to me that it may be inconsistent. – Brian Bi Aug 12 '19 at 19:25
  • Don't forget that because ptr are trivial types, technically you can always use an "invalid" ptr if there is some object that address. – curiousguy Aug 13 '19 at 16:55

1 Answers1

1

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.

darune
  • 10,480
  • 2
  • 24
  • 62