#pragma once #if __cplusplus >= 202002L #include #include #include #include #include #include #include #include #include namespace stdx { inline namespace v1 { template constexpr auto apply(F &&f, Ts &&...ts) { constexpr auto total_num_elements = (std::size_t{} + ... + stdx::tuple_size_v>); [[maybe_unused]] constexpr auto element_indices = [&] { std::array indices{}; [[maybe_unused]] auto p = indices.data(); ((p = std::remove_cvref_t::fill_inner_indices(p)), ...); [[maybe_unused]] auto q = indices.data(); [[maybe_unused]] std::size_t n{}; ((q = std::remove_cvref_t::fill_outer_indices(q, n++)), ...); return indices; }(); [[maybe_unused]] auto outer_tuple = stdx::tuple{std::forward(ts)...}; return [&](std::index_sequence) { return std::forward(f)( std::move(outer_tuple)[index] [index]...); }(std::make_index_sequence{}); } template [[nodiscard]] constexpr auto tuple_cat(Ts &&...ts) { if constexpr (sizeof...(Ts) == 0) { return stdx::tuple<>{}; } else if constexpr (sizeof...(Ts) == 1) { return (ts, ...); } else { constexpr auto total_num_elements = (std::size_t{} + ... + stdx::tuple_size_v>); [[maybe_unused]] constexpr auto element_indices = [&] { std::array indices{}; auto p = indices.data(); ((p = std::remove_cvref_t::fill_inner_indices(p)), ...); auto q = indices.data(); std::size_t n{}; ((q = std::remove_cvref_t::fill_outer_indices(q, n++)), ...); return indices; }(); [[maybe_unused]] auto outer_tuple = stdx::tuple{std::forward(ts)...}; return [&](std::index_sequence) { using T = stdx::tuple])>>...>; return T{ std::move(outer_tuple)[index] [index]...}; }(std::make_index_sequence{}); } } template [[nodiscard]] constexpr auto tuple_cons(T &&t, Tup &&tup) { using tuple_t = std::remove_cvref_t; return [&](std::index_sequence) { return stdx::tuple, stdx::tuple_element_t...>{ std::forward(t), std::forward(tup)[index]...}; }(std::make_index_sequence>{}); } template [[nodiscard]] constexpr auto tuple_snoc(Tup &&tup, T &&t) { using tuple_t = std::remove_cvref_t; return [&](std::index_sequence) { return stdx::tuple..., std::remove_cvref_t>{ std::forward(tup)[index]..., std::forward(t)}; }(std::make_index_sequence>{}); } template [[nodiscard]] constexpr auto tuple_push_front(T &&t, Tup &&tup) -> decltype(auto) { return tuple_cons(std::forward(t), std::forward(tup)); } template [[nodiscard]] constexpr auto tuple_push_back(Tup &&tup, T &&t) -> decltype(auto) { return tuple_snoc(std::forward(tup), std::forward(t)); } template