diff --git a/src/core/include/units/bits/external/type_list.h b/src/core/include/units/bits/external/type_list.h index 88f52a87..ac99b80a 100644 --- a/src/core/include/units/bits/external/type_list.h +++ b/src/core/include/units/bits/external/type_list.h @@ -59,6 +59,55 @@ struct type_list_size_impl> : std::integral_constant inline constexpr std::size_t type_list_size = detail::type_list_size_impl::value; + +// map + +namespace detail { + +template typename To> +struct type_list_map_impl; + +template typename From, template typename To, typename... Args> +struct type_list_map_impl, To> { + using type = To; +}; + +} // namespace detail + +template typename To> +using type_list_map = TYPENAME detail::type_list_map_impl::type; + + +// element + +namespace detail { + +template +struct type_list_leaf { + using type = T; +}; + +template +struct indexed_type_list_impl; + +template +struct indexed_type_list_impl, Ts...> : type_list_leaf... {}; + +template +std::type_identity type_list_element_func(const type_list_leaf&); + +} // namespace detail + +template +struct indexed_type_list : detail::indexed_type_list_impl, Ts...> {}; + +template +using type_list_element_indexed = typename decltype(detail::type_list_element_func(std::declval()))::type; + +template +using type_list_element = type_list_element_indexed, I>; + + // front namespace detail { @@ -76,6 +125,13 @@ struct type_list_front_impl> { template using type_list_front = TYPENAME detail::type_list_front_impl::type; + +// back + +template +using type_list_back = type_list_element - 1>; + + // push_front namespace detail { @@ -93,6 +149,7 @@ struct type_list_push_front_impl, NewTypes...> { template using type_list_push_front = TYPENAME detail::type_list_push_front_impl::type; + // push_back namespace detail { @@ -110,6 +167,7 @@ struct type_list_push_back_impl, NewTypes...> { template using type_list_push_back = TYPENAME detail::type_list_push_back_impl::type; + // join namespace detail { @@ -129,46 +187,29 @@ struct type_list_join_impl, List, Rest...> { template using type_list_join = TYPENAME detail::type_list_join_impl::type; + // split namespace detail { -template typename List, std::size_t Idx, std::size_t N, typename... Types> -struct split_impl; +template +struct type_list_split_impl; -template typename List, std::size_t Idx, std::size_t N> -struct split_impl { - using first_list = List<>; - using second_list = List<>; -}; - -template typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest> - requires(Idx < N) -struct split_impl : split_impl { - using base = split_impl; - using first_list = TYPENAME type_list_push_front_impl::type; - using second_list = TYPENAME base::second_list; -}; - -template typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest> -struct split_impl : split_impl { - using base = split_impl; - using first_list = TYPENAME base::first_list; - using second_list = TYPENAME type_list_push_front_impl::type; +template typename List, typename... Args, std::size_t... First, std::size_t... Second> +struct type_list_split_impl, std::index_sequence, std::index_sequence> { + using indexed_list = indexed_type_list; + using first_list = List...>; + using second_list = List...>; }; } // namespace detail template -struct type_list_split; + requires(N <= type_list_size) +struct type_list_split : + detail::type_list_split_impl, + std::make_index_sequence - N>> {}; -template typename List, std::size_t N, typename... Types> -struct type_list_split, N> { - static_assert(N <= sizeof...(Types), "Invalid index provided"); - using split = detail::split_impl; - using first_list = TYPENAME split::first_list; - using second_list = TYPENAME split::second_list; -}; // split_half @@ -178,6 +219,7 @@ struct type_list_split_half; template typename List, typename... Types> struct type_list_split_half> : type_list_split, (sizeof...(Types) + 1) / 2> {}; + // merge_sorted namespace detail { @@ -200,7 +242,6 @@ struct type_list_merge_sorted_impl, List, Pred> { using type = List; }; - template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, template typename Pred> requires Pred::value @@ -221,6 +262,7 @@ struct type_list_merge_sorted_impl, List typename Pred> using type_list_merge_sorted = TYPENAME detail::type_list_merge_sorted_impl::type; + // sort namespace detail { @@ -252,23 +294,6 @@ struct type_list_sort_impl, Pred> { template typename Pred> using type_list_sort = TYPENAME detail::type_list_sort_impl::type; -// map - -namespace detail { - -template typename To> -struct type_list_map_impl; - -template typename From, template typename To, typename... Args> -struct type_list_map_impl, To> { - using type = To; -}; - -} // namespace detail - -template typename To> -using type_list_map = TYPENAME detail::type_list_map_impl::type; - } // namespace units UNITS_DIAGNOSTIC_POP diff --git a/test/unit_test/static/type_list_test.cpp b/test/unit_test/static/type_list_test.cpp index 81742907..9ab7bba4 100644 --- a/test/unit_test/static/type_list_test.cpp +++ b/test/unit_test/static/type_list_test.cpp @@ -43,6 +43,23 @@ static_assert(type_list_size> == 1); static_assert(type_list_size> == 2); static_assert(type_list_size> == 3); +// type_list_map + +template +struct other_list; + +static_assert(is_same_v, other_list>, other_list<>>); +static_assert(is_same_v, other_list>, other_list>); +static_assert(is_same_v, other_list>, other_list>); + +// type_list_element + +static_assert(is_same_v, 0>, int>); +static_assert(is_same_v, 0>, int>); +static_assert(is_same_v, 1>, double>); +static_assert(is_same_v, 2>, float>); +static_assert(is_same_v, 3>, long>); + // type_list_front template typename List> @@ -53,6 +70,16 @@ static_assert(is_same_v>, int>); static_assert(is_same_v>, long>); static_assert(is_same_v>, float>); +// type_list_back + +template typename List> +concept type_list_back_invalid_for_empty_list = !requires { typename type_list_back>; }; + +static_assert(type_list_back_invalid_for_empty_list); +static_assert(is_same_v>, int>); +static_assert(is_same_v>, long>); +static_assert(is_same_v>, float>); + // type_list_push_front static_assert(is_same_v, int>, type_list>); @@ -156,13 +183,4 @@ static_assert(is_same_v, constant_less>, type_l static_assert(is_same_v, constant_less>, type_list>); static_assert(is_same_v, constant_less>, type_list>); -// type_list_map - -template -struct other_list; - -static_assert(is_same_v, other_list>, other_list<>>); -static_assert(is_same_v, other_list>, other_list>); -static_assert(is_same_v, other_list>, other_list>); - } // namespace