Accessing implicitly-created arrays

1 day ago 3
ARTICLE AD BOX

storage_ points to an array of std::bytes and, AFAIU, under current standard wording, reinterpret_cast<T*>(storage_) still does as far as the compiler is concerned (https://eel.is/c++draft/expr.reinterpret.cast#7 does speak about actual object but of pointer type).
You just need to respect alignment (which you do).
Using std::launder, the compiler does not know anymore what you are doing with the pointer. As far as it is concerned again, it gets back the memory location of a T. And it happens to be the one pointed by storage_. It is only well defined if there is actually a T object is living there (the precondition you mentioned: https://eel.is/c++draft/ptr.launder).

So this is the correct way to access the objects within the storage.
Note: there are discussions to remove the need for this std::launder in your situation: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3006r1.html

Now you are right to distrust your construct_at call.

Merely do: std::construct_at(reinterpret_cast<T*>(storage_) + size_, t);

It is equivalent to ::new (static_cast<void*>(storage_)+ size_) T(t); (https://eel.is/c++draft/specialized.construct#3)

So there is no need for a possibly invalid std::launder there.

Side note: I'm unsure if you are getting a proper array of T with data() (which would allow for pointer arithmetic) or if you merely get access to the first T object. https://eel.is/c++draft/allocator.requirements.general#36 seems to imply that the answer is yes:

[Example 1: When reusing storage denoted by some pointer value p, launder(reinterpret_cast<T*>(new (p) byte[n * sizeof(T)])) can be used to implicitly create a suitable array object and obtain a pointer to it. — end example]

But you still have to start the lifetime of the elements (as you do), except if T is an implicit lifetime type.

Oersted's user avatar

2 Comments

Thank you for such a clear explanation! One more question: in your last quote (eel.is/c++draft/allocator.requirements.general#36), it seems that launder is also invoked despite preconditions not being met. Do you think that is intentional (as in, the standard says this is legal, so it is)?

2026-03-24T19:44:12.167Z+00:00

I'm not 100% confident about what I'll said: Array types are implicit lifetime type so, in the example, what is created is a n array of n T objects by these objects themselves are not necessarily alive (especially if they are not ILT themselves). Thus you have a live object (the array) and std::launder precondition is met. Yet you cannot do much with that except pointer arithmetic. You cannot access the element until you start their lifetime.

2026-03-25T07:34:22.51Z+00:00

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Read Entire Article