Date: Sat, 30 Nov 2024 17:30:01 +0000
On Sat, 30 Nov 2024, 14:16 Desmond Gold via Std-Proposals, <
std-proposals_at_[hidden]> wrote:
>
>
> ---------- Forwarded message ---------
> From: Desmond Gold <desmondbongcawel922_at_[hidden]>
> Date: Sat, Nov 30, 2024 at 8:15 PM
> Subject: destructurable std::integer_sequence
> To: <std-proposals_at_[hidden]>
>
>
> After P1061R10 <https://wg21.link/P1061R10> has been approved for C++26,
> it's now time to let std::integer_sequence be a destructurable type for
> improved usability while still remain its niche
>
> auto [...Is] = std::make_index_sequence<N>();
>
> This addition helps simplify metaprogramming implementations that rely on
> std::integer_sequence. Most of these implementations declare another
> helper function that takes std::integer_sequence that does the actual
> work. But with this addition, you don't need to do that.
>
> // before:
> template <typename Array, std::size_t... I>
> constexpr auto array_to_tuple_impl(const Array& a,
> std::index_sequence<I...>)
> {
> return std::make_tuple(a[I]...);
> }
>
> template <typename T, std::size_t N, typename Indx =
> std::make_index_sequence<N>>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> return details::array_to_tuple_impl(a, Indx{});
> }
>
> // after:
> template <typename T, std::size_t N>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> auto [...Is] = std::make_index_sequence<N>();
> return std::make_tuple(a[Is]...);
> }
>
Can't you just do:
auto& [e...] = a;
return std::tuple(e...);
?
> One of the motivating examples of P1061R10 which requires
> std::index_sequence to be destructurable:
> template <class P, class Q>
> auto dot_product(P p, Q q) {
> // no helper function necessary!
> auto [...Is] = std::make_index_sequence<std::tuple_size_v<P>>{};
> return (... + (std::get<Is>(p) * std::get<Is>(q)));
> }
>
> There are two options in making these destructurable sequences possible:
> 1.) destructured into individual std::integral_constant:
>
> template<typename _Tp, _Tp... _Is>
> struct tuple_size<std::integer_sequence<_Tp, _Is...>>
> : std::integral_constant<std::size_t, sizeof...(_Is)> { };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> struct tuple_element<_I, std::integer_sequence<_Tp, _Is...>>
> { using type = std::integral_constant<_Tp, _Is...[_I]>; };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> constexpr std::integral_constant<_Tp, _Is...[_I]>
> get(std::integer_sequence<_Tp, _Is...>) noexcept
> { return {}; }
>
> 2.) destructured into constant integers:
>
> template<typename _Tp, _Tp... _Is>
> struct tuple_size<std::integer_sequence<_Tp, _Is...>>
> : std::integral_constant<std::size_t, sizeof...(_Is)> { };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> struct tuple_element<_I, std::integer_sequence<_Tp, _Is...>>
> { using type = _Tp; };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> constexpr _Tp get(std::integer_sequence<_Tp, _Is...>) noexcept
> { return _Is...[_I]; }
>
> There are notable differences between these options.
> - Option 1 decomposes into std::integral_constant of different types. This
> allows you to declare like this which is usable in constant-expressions
> converted into underlying value type.
>
> auto [...Is] = std::make_index_sequence<N>();
>
> - Option 2 decomposes into integral constants of the same value type. This
> requires you to declare structured binding as constexpr (made possible by
> P2686R5 <https://wg21.link/P2686R5>).
>
> constexpr auto [...Is] = std::make_index_sequence<N>();
>
> However, there is one problem. What if the integer sequence is empty? I
> don't know if P1061R10 permits empty structured binding packs from an
> object of zero tuple size. If this isn't currently allowed, then I believe
> this is the hole of the proposal which needs a core language fix
> (probably?) or worse never add this library feature because of this. Or add
> this and make workarounds such as:
>
> template <typename T, std::size_t N>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> if constexpr (N != 0)
> {
> auto [...Is] = std::make_index_sequence<N>();
> return std::make_tuple(a[Is]...);
> }
> else
> {
> return std::make_tuple();
> }
> }
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
>
>
> ---------- Forwarded message ---------
> From: Desmond Gold <desmondbongcawel922_at_[hidden]>
> Date: Sat, Nov 30, 2024 at 8:15 PM
> Subject: destructurable std::integer_sequence
> To: <std-proposals_at_[hidden]>
>
>
> After P1061R10 <https://wg21.link/P1061R10> has been approved for C++26,
> it's now time to let std::integer_sequence be a destructurable type for
> improved usability while still remain its niche
>
> auto [...Is] = std::make_index_sequence<N>();
>
> This addition helps simplify metaprogramming implementations that rely on
> std::integer_sequence. Most of these implementations declare another
> helper function that takes std::integer_sequence that does the actual
> work. But with this addition, you don't need to do that.
>
> // before:
> template <typename Array, std::size_t... I>
> constexpr auto array_to_tuple_impl(const Array& a,
> std::index_sequence<I...>)
> {
> return std::make_tuple(a[I]...);
> }
>
> template <typename T, std::size_t N, typename Indx =
> std::make_index_sequence<N>>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> return details::array_to_tuple_impl(a, Indx{});
> }
>
> // after:
> template <typename T, std::size_t N>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> auto [...Is] = std::make_index_sequence<N>();
> return std::make_tuple(a[Is]...);
> }
>
Can't you just do:
auto& [e...] = a;
return std::tuple(e...);
?
> One of the motivating examples of P1061R10 which requires
> std::index_sequence to be destructurable:
> template <class P, class Q>
> auto dot_product(P p, Q q) {
> // no helper function necessary!
> auto [...Is] = std::make_index_sequence<std::tuple_size_v<P>>{};
> return (... + (std::get<Is>(p) * std::get<Is>(q)));
> }
>
> There are two options in making these destructurable sequences possible:
> 1.) destructured into individual std::integral_constant:
>
> template<typename _Tp, _Tp... _Is>
> struct tuple_size<std::integer_sequence<_Tp, _Is...>>
> : std::integral_constant<std::size_t, sizeof...(_Is)> { };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> struct tuple_element<_I, std::integer_sequence<_Tp, _Is...>>
> { using type = std::integral_constant<_Tp, _Is...[_I]>; };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> constexpr std::integral_constant<_Tp, _Is...[_I]>
> get(std::integer_sequence<_Tp, _Is...>) noexcept
> { return {}; }
>
> 2.) destructured into constant integers:
>
> template<typename _Tp, _Tp... _Is>
> struct tuple_size<std::integer_sequence<_Tp, _Is...>>
> : std::integral_constant<std::size_t, sizeof...(_Is)> { };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> struct tuple_element<_I, std::integer_sequence<_Tp, _Is...>>
> { using type = _Tp; };
>
> template<std::size_t _I, typename _Tp, _Tp... _Is>
> constexpr _Tp get(std::integer_sequence<_Tp, _Is...>) noexcept
> { return _Is...[_I]; }
>
> There are notable differences between these options.
> - Option 1 decomposes into std::integral_constant of different types. This
> allows you to declare like this which is usable in constant-expressions
> converted into underlying value type.
>
> auto [...Is] = std::make_index_sequence<N>();
>
> - Option 2 decomposes into integral constants of the same value type. This
> requires you to declare structured binding as constexpr (made possible by
> P2686R5 <https://wg21.link/P2686R5>).
>
> constexpr auto [...Is] = std::make_index_sequence<N>();
>
> However, there is one problem. What if the integer sequence is empty? I
> don't know if P1061R10 permits empty structured binding packs from an
> object of zero tuple size. If this isn't currently allowed, then I believe
> this is the hole of the proposal which needs a core language fix
> (probably?) or worse never add this library feature because of this. Or add
> this and make workarounds such as:
>
> template <typename T, std::size_t N>
> constexpr auto array_to_tuple(const std::array<T, N>& a)
> {
> if constexpr (N != 0)
> {
> auto [...Is] = std::make_index_sequence<N>();
> return std::make_tuple(a[Is]...);
> }
> else
> {
> return std::make_tuple();
> }
> }
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2024-11-30 17:31:22