I have a code similar to the following which uses an allocator to allocate raw memory, and then uses std::uninitialized_default_construct_n (or another function of the same family) to construct objects in it.
std::allocator<T> allocator;
T* buffer = allocator.allocate(n);
std::uninitialized_default_construct_n(buffer, n);
buffer = std::launder(buffer); // needed?
...
std::destroy_n(buffer, n);
allocator.deallocate(buffer, n);
Is it needed to use std::launder on the pointer after this, to inform the compiler that the pointer now points to T objects? Or do the construct functions do the same thing implicitly?
It is for a container class, where I want to avoid value-constructing (instead of default-constructing) objects that will later be copy-assigned into.
No,
std::laundermay only be necessary in the allocator itself, not at the point where it's used. Note the effect ofallocate:- [allocator.requirements.general]
allocateFurthermore,
std::allocator::allocateEven though the lifetime of the array elements has not yet begun, the lifetime of the surrounding array has begun.
std::uninitialized_default_construct_nbegins the lifetime of elements and does not end the lifetime of the surrounding array. This means that the elements of the array can be reached normally using the returnedbufferpointer, which can be used in limited ways ([basic.life] p7).std::launderwould only be necessary if you were given a pointer whose provenance does not lead back to aTobject (or array thereof) at all. Example 1 in the quote shows how someone who implementsallocatecould uselaunder.