1+ #pragma once
2+
3+ #include < type_traits>
4+
5+ #include " ../meta_funcs/metafuncs_utility.hpp"
6+ #include " ./sequence.hpp"
7+ #include " ./tuple_utils.hpp"
8+
9+ namespace core ::meta::utils {
10+
11+ /* *
12+ * @brief Expands a template with index-based transformations
13+ *
14+ * @tparam F Template template parameter to apply
15+ * @tparam T Input type to transform
16+ * @tparam U Index sequence for expansion
17+ * @tparam values... Sequence of values
18+ * @tparam N Sequence of indices
19+ * @tparam V Offset value for indices
20+ *
21+ * Specialization for types with value parameters and true condition
22+ */
23+ template <template <auto , typename > typename F,
24+ template <typename , auto ...> typename T, typename U, auto ... values,
25+ auto ... N>
26+ struct expand <F, T<U, values...>, std::index_sequence<N...>, true > {
27+ using args = T<U, values...>; // /< Original argument type
28+ using type = tuple_t <c_<typev<F<N, args>>, U>...>; // /< Resulting tuple type
29+ };
30+
31+ /* *
32+ * @brief Expands a template with index-based transformations
33+ *
34+ * Specialization for types with value parameters and false condition
35+ */
36+ template <template <auto , typename > typename F,
37+ template <typename , auto ...> typename T, typename U, auto ... values,
38+ auto ... N>
39+ struct expand <F, T<U, values...>, std::index_sequence<N...>, false > {
40+ using args = T<U, values...>; // /< Original argument type
41+ using type = tuple_t <
42+ index_type<N, c_<typev<F<N, args>>, U>>...>; // /< Resulting tuple type
43+ // /< with indexed elements
44+ };
45+
46+ /* *
47+ * @brief Empty expansion case for regular template types
48+ *
49+ * Specialization when index sequence is empty
50+ */
51+ template <template <auto , typename > typename F,
52+ template <typename ...> typename T, typename ... Args, auto V>
53+ struct expand <F, T<Args...>, std::index_sequence<>, V> {
54+ using type = clear_t <T<Args...>>; // /< Cleared input type
55+ };
56+
57+ /* *
58+ * @brief Empty expansion case for value-parameterized types
59+ *
60+ * Specialization when index sequence is empty
61+ */
62+ template <template <auto , typename > typename F,
63+ template <typename , auto ...> typename T, typename U, auto ... values,
64+ auto V>
65+ struct expand <F, T<U, values...>, std::index_sequence<>, V> {
66+ using type = clear_t <T<U, values...>>; // /< Cleared input type
67+ };
68+
69+ /* *
70+ * @brief General expansion implementation
71+ *
72+ * Handles both tuple-like and integer sequence outputs
73+ */
74+ template <template <auto , typename > typename F, typename T, auto ... N, auto V>
75+ struct expand <F, T, std::index_sequence<N...>, V> {
76+ /* *
77+ * @brief Implementation for tuple-like output
78+ */
79+ template <typename W, bool b>
80+ struct impl {
81+ using type =
82+ tuple_t <typeof_t <F<N + V, W>>...>; // /< Tuple of transformed types
83+ };
84+
85+ /* *
86+ * @brief Implementation for integer sequence output
87+ */
88+ template <typename W>
89+ struct impl <W, false > {
90+ using type = std::integer_sequence<
91+ W, typev<F<N + V, W>>...>; // /< Integer sequence of transformed values
92+ };
93+
94+ using head = typeof_t <
95+ F<head_v<std::index_sequence<N...>, V>, T>>; // /< First transformed type
96+ using type =
97+ typeof_t <impl<T, negav<has_value_type<head>>>>; // /< Select appropriate
98+ // /< implementation
99+ };
100+
101+ /* *
102+ * @brief Empty expansion case
103+ */
104+ template <template <auto , typename > typename F, typename T, auto V>
105+ struct expand <F, T, std::index_sequence<>, V> {
106+ using type = tuple_t <>; // /< Empty tuple result
107+ };
108+
109+ /* *
110+ * @brief Convenience alias for expand::type
111+ */
112+ template <template <auto , typename > typename F, typename T,
113+ typename U = index_sequence_of_t <T>, auto V = 0 >
114+ using expand_t = typeof_t <expand<F, T, U, V>>;
115+
116+ /* *
117+ * @brief Conditional expansion
118+ *
119+ * Expands only if condition B is true, otherwise returns original type
120+ */
121+ template <bool B, template <auto , typename > typename F, typename T,
122+ typename U = index_sequence_of_t <T>, auto V = 0 >
123+ using expand_if =
124+ std::conditional_t <B, expand<F, T, U, V>, std::type_identity<T>>;
125+
126+ /* *
127+ * @brief Convenience alias for expand_if::type
128+ */
129+ template <bool B, template <auto , typename > typename F, typename T,
130+ typename U = index_sequence_of_t <T>, auto V = 0 >
131+ using expand_if_t = typeof_t <expand_if<B, F, T, U, V>>;
132+
133+ /* *
134+ * @brief Expansion using element extraction
135+ */
136+ template <typename T, typename U = index_sequence_of_t <T>, auto V = 0 >
137+ using expand_of = expand<element, T, U, V>;
138+
139+ /* *
140+ * @brief Convenience alias for expand_of::type
141+ */
142+ template <typename T, typename U = index_sequence_of_t <T>, auto V = 0 >
143+ using expand_of_t = typeof_t <expand_of<T, U, V>>;
144+
145+ } // namespace core::meta::utils
0 commit comments