> It's much easier to call `.release()` on a properly managed RAII return object, than it is to remember to call `delete` (or whatever) on a non-RAII return value.
I agree, and that functionality can be created on top of the proposed function by calling make_contiguous_objects (or new_..) and destroy_contiguous object.
But that would be an extension to the raw functionality. I mean, if we find the raw functionality to have unfixable problems, there is no point in discussing the RAII version.
>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.
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.
> If you construct objects, then you need the manager to remember how many of each type of object to destroy (not just the total number of bytes, which the C++ runtime remembers for us for free anyway).
That is why the API returns a tuple of spans. That is the object that remembers how many and which type.