> 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.

Best Regards,
Breno G.


On Sun, Mar 12, 2023 at 2:46 PM Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
On Sun, 12 Mar 2023 at 19:42, Arthur O'Dwyer via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:

> 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.

Why on earth would this be the latter? An allocator can already be
used for getting storage.