Date: Sat, 18 Mar 2023 20:12:25 -0400
On Sat, Mar 18, 2023 at 5:26 AM Jens Maurer <jens.maurer_at_[hidden]> wrote:
> Would an interface like
>
> template<class ... Ts>
> std::tuple<Ts * ...> allocate_arrays( decltype(std::void_t<Ts>,
> std::size_t>)... );
>
> help most of the use-cases? If someone wants construction,
> the std::uninitialized_* algorithms are at their service.
>
FWIW, I think so too; except that I would wrap it in a node-handle-esque
RAII type. `allocate_arrays` *knows* exactly how the return value needs to
be cleaned up, so it should return a type that expresses that to the
caller. The caller should be able to call `.release()` on that return value
in order to claim "I'll do the cleanup manually"... or, even more likely
IMHO, the caller shouldn't be able to do that, because the caller shouldn't
be *permitted* to know how the arrays were allocated nor how to clean them
up. That should be an implementation detail which is left completely up to
the implementation.
This implementation-detail business raises a new question: Suppose I ask
for 1 int16, 1 int64, and 3 int32s. Should the implementation be required
to allocate exactly
i16 (pad48) i64 i32 i32 i32
or should it be permitted to allocate e.g.
i32 i32 i32 i16 (pad16) i64
instead? I *tentatively* suggest that the latter should *not* be permitted
— because one of the use-cases for this thing is the "we know where you
live" optimization in make_shared, and that optimization works only if the
location of the i64 can be computed from the location of the i16 plus some
pointer math. If the second pointer in your returned std::tuple<Ts*...>
isn't mechanically computable from the first pointer, and so on, then the
thing isn't useful. This suggests that std::tuple<Ts*...> is the wrong
return type, per the guideline "Make illegal states unrepresentable": it
spends many extra CPU registers (maybe even spilling to the stack) in order
to communicate information that the caller can compute themselves and/or
doesn't want to compute in the first place.
But I don't know what a "better" return type would look like. :)
> (The std::uninitialized_* algorithms seem to deal in pointers-to-T
> even when pointing to not-yet-constructed memory.)
>
Yes; <off-topic> and that's the right choice.
https://quuxplusone.github.io/blog/2018/06/08/raw-memory-and-t-star/#notice-that-when-we-call-index-t
</off-topic>
Cheers,
Arthur
> Would an interface like
>
> template<class ... Ts>
> std::tuple<Ts * ...> allocate_arrays( decltype(std::void_t<Ts>,
> std::size_t>)... );
>
> help most of the use-cases? If someone wants construction,
> the std::uninitialized_* algorithms are at their service.
>
FWIW, I think so too; except that I would wrap it in a node-handle-esque
RAII type. `allocate_arrays` *knows* exactly how the return value needs to
be cleaned up, so it should return a type that expresses that to the
caller. The caller should be able to call `.release()` on that return value
in order to claim "I'll do the cleanup manually"... or, even more likely
IMHO, the caller shouldn't be able to do that, because the caller shouldn't
be *permitted* to know how the arrays were allocated nor how to clean them
up. That should be an implementation detail which is left completely up to
the implementation.
This implementation-detail business raises a new question: Suppose I ask
for 1 int16, 1 int64, and 3 int32s. Should the implementation be required
to allocate exactly
i16 (pad48) i64 i32 i32 i32
or should it be permitted to allocate e.g.
i32 i32 i32 i16 (pad16) i64
instead? I *tentatively* suggest that the latter should *not* be permitted
— because one of the use-cases for this thing is the "we know where you
live" optimization in make_shared, and that optimization works only if the
location of the i64 can be computed from the location of the i16 plus some
pointer math. If the second pointer in your returned std::tuple<Ts*...>
isn't mechanically computable from the first pointer, and so on, then the
thing isn't useful. This suggests that std::tuple<Ts*...> is the wrong
return type, per the guideline "Make illegal states unrepresentable": it
spends many extra CPU registers (maybe even spilling to the stack) in order
to communicate information that the caller can compute themselves and/or
doesn't want to compute in the first place.
But I don't know what a "better" return type would look like. :)
> (The std::uninitialized_* algorithms seem to deal in pointers-to-T
> even when pointing to not-yet-constructed memory.)
>
Yes; <off-topic> and that's the right choice.
https://quuxplusone.github.io/blog/2018/06/08/raw-memory-and-t-star/#notice-that-when-we-call-index-t
</off-topic>
Cheers,
Arthur
Received on 2023-03-19 00:12:38