mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-09 23:24:27 +02:00
feat: type_list_element
, type_list_back
added; type_list_split
refactored
This commit is contained in:
119
src/core/include/units/bits/external/type_list.h
vendored
119
src/core/include/units/bits/external/type_list.h
vendored
@@ -59,6 +59,55 @@ struct type_list_size_impl<List<Types...>> : std::integral_constant<std::size_t,
|
||||
template<TypeList List>
|
||||
inline constexpr std::size_t type_list_size = detail::type_list_size_impl<List>::value;
|
||||
|
||||
|
||||
// map
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, template<typename...> typename To>
|
||||
struct type_list_map_impl;
|
||||
|
||||
template<template<typename...> typename From, template<typename...> typename To, typename... Args>
|
||||
struct type_list_map_impl<From<Args...>, To> {
|
||||
using type = To<Args...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList From, template<typename...> typename To>
|
||||
using type_list_map = TYPENAME detail::type_list_map_impl<From, To>::type;
|
||||
|
||||
|
||||
// element
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t I, typename T>
|
||||
struct type_list_leaf {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename Seq, typename...>
|
||||
struct indexed_type_list_impl;
|
||||
|
||||
template<std::size_t... Is, typename... Ts>
|
||||
struct indexed_type_list_impl<std::index_sequence<Is...>, Ts...> : type_list_leaf<Is, Ts>... {};
|
||||
|
||||
template<std::size_t I, typename T>
|
||||
std::type_identity<T> type_list_element_func(const type_list_leaf<I, T>&);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename... Ts>
|
||||
struct indexed_type_list : detail::indexed_type_list_impl<std::index_sequence_for<Ts...>, Ts...> {};
|
||||
|
||||
template<TypeList List, std::size_t I>
|
||||
using type_list_element_indexed = typename decltype(detail::type_list_element_func<I>(std::declval<List>()))::type;
|
||||
|
||||
template<TypeList List, std::size_t I>
|
||||
using type_list_element = type_list_element_indexed<type_list_map<List, indexed_type_list>, I>;
|
||||
|
||||
|
||||
// front
|
||||
|
||||
namespace detail {
|
||||
@@ -76,6 +125,13 @@ struct type_list_front_impl<List<T, Ts...>> {
|
||||
template<TypeList List>
|
||||
using type_list_front = TYPENAME detail::type_list_front_impl<List>::type;
|
||||
|
||||
|
||||
// back
|
||||
|
||||
template<TypeList List>
|
||||
using type_list_back = type_list_element<List, type_list_size<List> - 1>;
|
||||
|
||||
|
||||
// push_front
|
||||
|
||||
namespace detail {
|
||||
@@ -93,6 +149,7 @@ struct type_list_push_front_impl<List<OldTypes...>, NewTypes...> {
|
||||
template<TypeList List, typename... Types>
|
||||
using type_list_push_front = TYPENAME detail::type_list_push_front_impl<List, Types...>::type;
|
||||
|
||||
|
||||
// push_back
|
||||
|
||||
namespace detail {
|
||||
@@ -110,6 +167,7 @@ struct type_list_push_back_impl<List<OldTypes...>, NewTypes...> {
|
||||
template<TypeList List, typename... Types>
|
||||
using type_list_push_back = TYPENAME detail::type_list_push_back_impl<List, Types...>::type;
|
||||
|
||||
|
||||
// join
|
||||
|
||||
namespace detail {
|
||||
@@ -129,46 +187,29 @@ struct type_list_join_impl<List<First...>, List<Second...>, Rest...> {
|
||||
template<TypeList... Lists>
|
||||
using type_list_join = TYPENAME detail::type_list_join_impl<Lists...>::type;
|
||||
|
||||
|
||||
// split
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename... Types>
|
||||
struct split_impl;
|
||||
template<typename List, typename First, typename Second>
|
||||
struct type_list_split_impl;
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N>
|
||||
struct split_impl<List, Idx, N> {
|
||||
using first_list = List<>;
|
||||
using second_list = List<>;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest>
|
||||
requires(Idx < N)
|
||||
struct split_impl<List, Idx, N, T, Rest...> : split_impl<List, Idx + 1, N, Rest...> {
|
||||
using base = split_impl<List, Idx + 1, N, Rest...>;
|
||||
using first_list = TYPENAME type_list_push_front_impl<typename base::first_list, T>::type;
|
||||
using second_list = TYPENAME base::second_list;
|
||||
};
|
||||
|
||||
template<template<typename...> typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest>
|
||||
struct split_impl<List, Idx, N, T, Rest...> : split_impl<List, Idx + 1, N, Rest...> {
|
||||
using base = split_impl<List, Idx + 1, N, Rest...>;
|
||||
using first_list = TYPENAME base::first_list;
|
||||
using second_list = TYPENAME type_list_push_front_impl<typename base::second_list, T>::type;
|
||||
template<template<typename...> typename List, typename... Args, std::size_t... First, std::size_t... Second>
|
||||
struct type_list_split_impl<List<Args...>, std::index_sequence<First...>, std::index_sequence<Second...>> {
|
||||
using indexed_list = indexed_type_list<Args...>;
|
||||
using first_list = List<type_list_element_indexed<indexed_list, First>...>;
|
||||
using second_list = List<type_list_element_indexed<indexed_list, sizeof...(First) + Second>...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList List, std::size_t N>
|
||||
struct type_list_split;
|
||||
requires(N <= type_list_size<List>)
|
||||
struct type_list_split :
|
||||
detail::type_list_split_impl<List, std::make_index_sequence<N>,
|
||||
std::make_index_sequence<type_list_size<List> - N>> {};
|
||||
|
||||
template<template<typename...> typename List, std::size_t N, typename... Types>
|
||||
struct type_list_split<List<Types...>, N> {
|
||||
static_assert(N <= sizeof...(Types), "Invalid index provided");
|
||||
using split = detail::split_impl<List, 0, N, Types...>;
|
||||
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<template<typename...> typename List, typename... Types>
|
||||
struct type_list_split_half<List<Types...>> : type_list_split<List<Types...>, (sizeof...(Types) + 1) / 2> {};
|
||||
|
||||
|
||||
// merge_sorted
|
||||
|
||||
namespace detail {
|
||||
@@ -200,7 +242,6 @@ struct type_list_merge_sorted_impl<List<>, List<Rhs...>, Pred> {
|
||||
using type = List<Rhs...>;
|
||||
};
|
||||
|
||||
|
||||
template<template<typename...> typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest,
|
||||
template<typename, typename> typename Pred>
|
||||
requires Pred<Lhs1, Rhs1>::value
|
||||
@@ -221,6 +262,7 @@ struct type_list_merge_sorted_impl<List<Lhs1, LhsRest...>, List<Rhs1, RhsRest...
|
||||
template<TypeList SortedList1, TypeList SortedList2, template<typename, typename> typename Pred>
|
||||
using type_list_merge_sorted = TYPENAME detail::type_list_merge_sorted_impl<SortedList1, SortedList2, Pred>::type;
|
||||
|
||||
|
||||
// sort
|
||||
|
||||
namespace detail {
|
||||
@@ -252,23 +294,6 @@ struct type_list_sort_impl<List<Types...>, Pred> {
|
||||
template<TypeList List, template<typename, typename> typename Pred>
|
||||
using type_list_sort = TYPENAME detail::type_list_sort_impl<List, Pred>::type;
|
||||
|
||||
// map
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, template<typename...> typename To>
|
||||
struct type_list_map_impl;
|
||||
|
||||
template<template<typename...> typename From, template<typename...> typename To, typename... Args>
|
||||
struct type_list_map_impl<From<Args...>, To> {
|
||||
using type = To<Args...>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<TypeList From, template<typename...> typename To>
|
||||
using type_list_map = TYPENAME detail::type_list_map_impl<From, To>::type;
|
||||
|
||||
} // namespace units
|
||||
|
||||
UNITS_DIAGNOSTIC_POP
|
||||
|
@@ -43,6 +43,23 @@ static_assert(type_list_size<type_list<int>> == 1);
|
||||
static_assert(type_list_size<type_list<int, int>> == 2);
|
||||
static_assert(type_list_size<type_list<int, long, int>> == 3);
|
||||
|
||||
// type_list_map
|
||||
|
||||
template<typename... Types>
|
||||
struct other_list;
|
||||
|
||||
static_assert(is_same_v<type_list_map<type_list<>, other_list>, other_list<>>);
|
||||
static_assert(is_same_v<type_list_map<type_list<int>, other_list>, other_list<int>>);
|
||||
static_assert(is_same_v<type_list_map<type_list<double, int>, other_list>, other_list<double, int>>);
|
||||
|
||||
// type_list_element
|
||||
|
||||
static_assert(is_same_v<type_list_element<type_list<int>, 0>, int>);
|
||||
static_assert(is_same_v<type_list_element<type_list<int, double, float, long>, 0>, int>);
|
||||
static_assert(is_same_v<type_list_element<type_list<int, double, float, long>, 1>, double>);
|
||||
static_assert(is_same_v<type_list_element<type_list<int, double, float, long>, 2>, float>);
|
||||
static_assert(is_same_v<type_list_element<type_list<int, double, float, long>, 3>, long>);
|
||||
|
||||
// type_list_front
|
||||
|
||||
template<template<typename...> typename List>
|
||||
@@ -53,6 +70,16 @@ static_assert(is_same_v<type_list_front<type_list<int>>, int>);
|
||||
static_assert(is_same_v<type_list_front<type_list<long, int>>, long>);
|
||||
static_assert(is_same_v<type_list_front<type_list<float, long, int>>, float>);
|
||||
|
||||
// type_list_back
|
||||
|
||||
template<template<typename...> typename List>
|
||||
concept type_list_back_invalid_for_empty_list = !requires { typename type_list_back<List<>>; };
|
||||
|
||||
static_assert(type_list_back_invalid_for_empty_list<type_list>);
|
||||
static_assert(is_same_v<type_list_back<type_list<int>>, int>);
|
||||
static_assert(is_same_v<type_list_back<type_list<int, long>>, long>);
|
||||
static_assert(is_same_v<type_list_back<type_list<int, long, float>>, float>);
|
||||
|
||||
// type_list_push_front
|
||||
|
||||
static_assert(is_same_v<type_list_push_front<type_list<>, int>, type_list<int>>);
|
||||
@@ -156,13 +183,4 @@ static_assert(is_same_v<type_list_sort<type_list<v2, v1>, constant_less>, type_l
|
||||
static_assert(is_same_v<type_list_sort<type_list<v2, v1, v3>, constant_less>, type_list<v1, v2, v3>>);
|
||||
static_assert(is_same_v<type_list_sort<type_list<v4, v3, v2, v1>, constant_less>, type_list<v1, v2, v3, v4>>);
|
||||
|
||||
// type_list_map
|
||||
|
||||
template<typename... Types>
|
||||
struct other_list;
|
||||
|
||||
static_assert(is_same_v<type_list_map<type_list<>, other_list>, other_list<>>);
|
||||
static_assert(is_same_v<type_list_map<type_list<v1>, other_list>, other_list<v1>>);
|
||||
static_assert(is_same_v<type_list_map<type_list<v1, v2>, other_list>, other_list<v1, v2>>);
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user