12#include <source_location>
18namespace sequoia::meta
24 using trial_type = void;
25 constexpr std::string_view trial_type_name{
"void"};
27 namespace wrapped_type
31 constexpr std::string_view name() noexcept
33 return std::source_location::current().function_name();
37 constexpr std::size_t prefix_length() noexcept
39 return name<trial_type>().find(trial_type_name);
43 constexpr std::size_t suffix_length() noexcept
45 return name<trial_type>().length() - prefix_length() - trial_type_name.length();
52 consteval std::string_view type_name()
54 using namespace impl::wrapped_type;
55 constexpr auto wrappedName{name<T>()};
56 constexpr auto prefixLength{prefix_length()};
57 constexpr auto nameLength{wrappedName.length() - prefixLength - suffix_length()};
58 return wrappedName.substr(prefixLength, nameLength);
61 template<
class T,
class U>
62 struct type_comparator : std::bool_constant<type_name<T>() < type_name<U>()>
65 template<class T, class U>
66 using type_comparator_t = type_comparator<T, U>::type;
68 template<class T, class U>
69 inline constexpr bool type_comparator_v{type_comparator<T, U>::value};
73 template<class T, class U, template<class, class> class Compare>
76 template<class T, class U, template<class, class> class Compare>
77 inline constexpr auto lower_bound_v{lower_bound<T, U, Compare>::value};
79 template<template<class...> class TT, class... Ts, class U, template<class, class> class Compare>
80 struct lower_bound<TT<Ts...>, U, Compare>
82 constexpr static std::size_t N{sizeof...(Ts)};
84 template<std::size_t Lower, std::size_t Upper>
85 requires (Lower <= Upper) && (Upper <= N)
86 constexpr static std::size_t get() noexcept {
87 if constexpr (Lower == Upper)
91 constexpr auto partition{(Lower + Upper) / 2};
92 if constexpr(Compare<std::tuple_element_t<partition, std::tuple<Ts...>>, U>::value)
93 return get<partition + 1, Upper>();
95 return get<Lower, partition>();
99 constexpr static std::size_t value{get<0, N>()};
104 template<class T, class U>
107 template<class T, class U>
108 using filter_t = filter<T, U>::type;
110 template<template<class...> class TT, class... Ts, std::size_t... Is>
111 requires ((Is < sizeof...(Ts)) && ...)
112 struct filter<TT<Ts...>, std::index_sequence<Is...>>
114 using type = TT<std::tuple_element_t<Is, std::tuple<Ts...>> ...>;
117 template<class T, template<class> class Trait>
118 struct filter_by_trait;
120 template<class T, template<class> class Trait>
121 using filter_by_trait_t = filter_by_trait<T, Trait>::type;
123 template<template<class...> class TT, class... Ts, template<class> class Trait>
124 struct filter_by_trait<TT<Ts...>, Trait>
126 using type = filter_t<TT<Ts...>, make_filtered_sequence<std::false_type, Trait, Ts...>>;
131 template<class T, std::size_t N>
134 template<class T, std::size_t N>
135 using drop_t = drop<T, N>::type;
137 template<template<class...> class TT, class... Ts, std::size_t N>
138 requires (N >= sizeof...(Ts))
139 struct drop<TT<Ts...>, N>
144 template<template<class...> class TT, class... Ts, std::size_t N>
145 struct drop<TT<Ts...>, N>
147 using type = filter_t<TT<Ts...>, shift_sequence_t<std::make_index_sequence<sizeof...(Ts) - N>, N>>;
152 template<class T, std::size_t N>
155 template<class T, std::size_t N>
156 using keep_t = keep<T, N>::type;
158 template<template<class...> class TT, class... Ts, std::size_t N>
159 requires (N >= sizeof...(Ts))
160 struct keep<TT<Ts...>, N>
162 using type = TT<Ts...>;
165 template<template<class...> class TT, class... Ts, std::size_t N>
166 struct keep<TT<Ts...>, N>
168 using type = filter_t<TT<Ts...>, std::make_index_sequence<N>>;
173 template<class T, class U, std::size_t I>
176 template<class T, class U, std::size_t I>
177 using insert_t = insert<T, U, I>::type;
179 template<template<class...> class TT, class U>
180 struct insert<TT<>, U, 0>
190 template<class... Ts>
191 using do_insert_t = do_insert<Ts...>::type;
193 template<template<class...> class TT, class T, class... Us, std::size_t... Is, std::size_t... Js>
194 struct do_insert<T, TT<Us...>, std::index_sequence<Is...>, std::index_sequence<Js...>>
196 using type = TT<std::tuple_element_t<Is, std::tuple<Us...>>..., T, std::tuple_element_t<Js, std::tuple<Us...>>...>;
200 template<template<class...> class TT, class... Us, class T, std::size_t I>
201 requires (I <= sizeof...(Us))
202 struct insert<TT<Us...>, T, I>
204 using type = impl::do_insert_t<T,
206 std::make_index_sequence<I>,
207 shift_sequence_t<std::make_index_sequence<sizeof...(Us) - I>, I>>;
212 template<class T, std::size_t I>
215 template<class T, std::size_t I>
216 using erase_t = erase<T, I>::type;
218 template<template<class...> class TT, class T, class... Ts>
219 struct erase<TT<T, Ts...>, 0>
221 using type = TT<Ts...>;
224 template<template<class...> class TT, class... Ts, std::size_t I>
225 struct erase<TT<Ts...>, I>
227 concat_sequences_t<std::make_index_sequence<I>,
228 shift_sequence_t<std::make_index_sequence<sizeof...(Ts)-I-1>, I+1>>>
233 template<class T, class U, template<class, class> class Compare>
236 template<class T, class U, template<class, class> class Compare>
237 using merge_t = merge<T, U, Compare>::type;
239 template<template<class...> class TT, class... Ts, template<class, class> class Compare>
240 struct merge<TT<Ts...>, TT<>, Compare>
242 using type = TT<Ts...>;
245 template<template<class...> class TT, class... Ts, template<class, class> class Compare>
246 requires (sizeof...(Ts) > 0)
247 struct merge<TT<>, TT<Ts...>, Compare>
249 using type = TT<Ts...>;
252 template<template<class...> class TT, class T, class U, template<class, class> class Compare>
253 struct merge<TT<T>, TT<U>, Compare>
255 using type = TT<U, T>;
258 template<template<class...> class TT, class T, class U, template<class, class> class Compare>
259 requires (Compare<T, U>::value)
260 struct merge<TT<T>, TT<U>, Compare>
262 using type = TT<T, U>;
267 template<class T, class U, std::size_t I, template<class, class> class Compare>
268 struct merge_from_position;
270 template<class T, class U, std::size_t I, template<class, class> class Compare>
271 using merge_from_position_t = merge_from_position<T, U, I, Compare>::type;
273 template<template<class...> class TT, class... Us, std::size_t I, template<class, class> class Compare>
274 struct merge_from_position<std::tuple<>, TT<Us...>, I, Compare>
276 using type = TT<Us...>;
279 template<template<class...> class TT, class T, class... Us, std::size_t I, template<class, class> class Compare>
280 struct merge_from_position<TT<T>, TT<Us...>, I, Compare>
282 constexpr static auto N{sizeof...(Us)};
283 constexpr static auto Pos{I + lower_bound_v<drop_t<TT<Us...>, I>, T, Compare>};
284 using type = insert_t<TT<Us...>, T, Pos>;
287 template<template<class...> class TT, class T, class... Ts, class... Us, std::size_t I, template<class, class> class Compare>
288 struct merge_from_position<TT<T, Ts...>, TT<Us...>, I, Compare>
290 using first_merge = merge_from_position<TT<T>, TT<Us...>, 0, Compare>;
291 using type = merge_from_position_t<TT<Ts...>, typename first_merge::type, first_merge::Pos + 1, Compare>;
295 template<template<class...> class TT, class... Ts, class... Us, template<class, class> class Compare>
296 requires (sizeof...(Ts) > 0) && (sizeof...(Us) > 0)
297 struct merge<TT<Ts...>, TT<Us...>, Compare> : impl::merge_from_position<TT<Ts...>, TT<Us...>, 0, Compare>
302 template<
class T,
template<
class,
class>
class Compare>
305 template<
class T,
template<
class,
class>
class Compare>
306 using stable_sort_t = stable_sort<T, Compare>::type;
308 template<
template<
class...>
class TT,
template<
class,
class>
class Compare>
309 struct stable_sort<TT<>, Compare>
314 template<
template<
class...>
class TT,
class T,
template<
class,
class>
class Compare>
315 struct stable_sort<TT<T>, Compare>
320 template<
template<
class...>
class TT,
class... Ts,
template<
class,
class>
class Compare>
321 struct stable_sort<TT<Ts...>, Compare>
323 constexpr static auto partition{
sizeof...(Ts) / 2};
324 using type = merge_t<stable_sort_t<keep_t<TT<Ts...>, partition>, Compare>,
325 stable_sort_t<drop_t<TT<Ts...>, partition>, Compare>,
331 template<
class T,
class U>
334 template<
class T,
class U>
335 inline constexpr std::size_t find_v{find<T, U>::index};
337 template<
template<
class...>
class TT,
class U>
340 constexpr static std::size_t index{};
343 template<
template<
class...>
class TT,
class T,
class... Ts,
class U>
344 struct find<TT<T, Ts...>, U>
346 constexpr static std::size_t index{std::is_same_v<T, U> ? 0 : 1 + find_v<TT<Ts...>, U>};