>And now I'm confused: Is this make_contiguous_objects or make_contiguous_storage? Because most library users will need the latter, not the former.
It's "_objects". I don't agree most library users would need the latter. At least it's not in the use cases I looked at.
You give the following use-cases in the paper:
(btw, you call this "the LLVM implementation," but it would be clearer to say "the libc++ implementation of make_shared")
requires allocation without construction (it needs to pass Args... to the ctor).
performs allocation without construction, although it probably doesn't care (its types being constructed are trivial).
requires allocation without construction (it doesn't want to construct `T` objects yet), although the current implementation wraps `T` in a union both for this reason and for other reasons, so default-constructing-the-union-type ends up doing the same thing as not-constructing, in the end.
Some might want to defer the initialization of some arrays, but then they use it like `std::make_contiguous_objects<Metadata, ElementAlignedStorage>(nElements, nElements)`
And manually do part of the work.
But make_contiguous objects would give the buffer size calculation (including alignment) and the exception-safe creation of the metadata array.
Right, that's why the storage-allocating version is still a value-add over "nothing at all." It does the buffer size calculation, including alignment, and hands back the component-array pointers to the caller. (Ville, this answers your question about "why is this better than just using the allocator directly.")
But I don't see any use-cases yet where we want the T objects to be default-constructed. Default-constructing the T objects is explicitly impossible in some cases and harmless but unnecessarily slow in others. We haven't yet seen a case where it's helpful. That doesn't mean you can't provide an additional entrypoint that does construct the Ts; it just means that we haven't yet seen a positive use-case for that entrypoint. All our use-cases so far are use-cases for the allocating-but-not-constructing entrypoint.