|
1 | 1 | #pragma once // TODO: __cpp_pack_indexing >= 202311L
|
2 | 2 |
|
3 |
| -#include "../tuple/get.h" |
4 | 3 | #include "../utility/value_wrapper.h"
|
5 |
| -#include "regular_type_sequence.h" |
6 |
| -#include "regular_value_sequence.h" |
7 |
| -#include "type.h" |
| 4 | +#include "object.h" |
| 5 | + |
| 6 | +#include <tuple> |
8 | 7 |
|
9 | 8 | #include "../compilation_config_in.h"
|
10 | 9 |
|
11 | 10 | namespace stdsharp::details
|
12 | 11 | {
|
13 |
| - template<typename... T> |
14 |
| - struct indexed_types |
| 12 | + struct type_indexer |
15 | 13 | {
|
16 |
| - private: |
17 |
| - template<typename U, std::size_t I> |
18 |
| - struct indexed_type : type_constant<U> |
| 14 | + template<typename T> |
| 15 | + struct filter |
19 | 16 | {
|
20 |
| - static constexpr type_constant<U> get_type(const index_constant<I> /*unused*/) noexcept |
21 |
| - { |
22 |
| - return {}; |
23 |
| - } |
| 17 | + consteval type_constant<T> get() const noexcept { return {}; } |
24 | 18 | };
|
25 | 19 |
|
26 |
| - public: |
27 |
| - template<typename = index_sequence_for<T...>> |
28 |
| - struct base; |
29 |
| - |
30 |
| - template<std::size_t... I> |
31 |
| - struct STDSHARP_EBO base<regular_value_sequence<I...>> : indexed_type<T, I>... |
| 20 | + struct invalid |
32 | 21 | {
|
33 |
| - using indexed_type<T, I>::get_type...; |
| 22 | + }; |
34 | 23 |
|
35 |
| - base() = default; |
| 24 | + template<> |
| 25 | + struct filter<invalid> |
| 26 | + { |
36 | 27 | };
|
37 | 28 |
|
38 |
| - using impl = base<>; |
| 29 | + public: |
| 30 | + template<std::size_t I, std::size_t... J, typename... T> |
| 31 | + static consteval auto impl( |
| 32 | + const std::index_sequence<J...> /*unused*/, |
| 33 | + const basic_type_sequence<T...> /*unused*/ |
| 34 | + ) |
| 35 | + { |
| 36 | + constexpr struct : filter<std::conditional_t<I == J, T, invalid>>... |
| 37 | + { |
| 38 | + } f{}; |
| 39 | + |
| 40 | + return f.get(); |
| 41 | + } |
| 42 | + |
| 43 | + template<std::size_t I, typename... T> |
| 44 | + using type = |
| 45 | + decltype(impl<I>(std::index_sequence_for<T...>{}, basic_type_sequence<T...>{}))::type; |
39 | 46 | };
|
40 | 47 | }
|
41 | 48 |
|
42 | 49 | namespace stdsharp
|
43 | 50 | {
|
44 |
| - template<typename... T> |
45 |
| - struct basic_indexed_types : details::indexed_types<T...>::impl |
| 51 | + template<std::size_t I, typename T> |
| 52 | + struct indexed_value : value_wrapper<T> |
46 | 53 | {
|
47 | 54 | };
|
48 | 55 |
|
49 |
| - template<typename... T> |
50 |
| - basic_indexed_types(std::type_identity<T>...) -> basic_indexed_types<T...>; |
51 |
| - |
52 |
| - template<typename... T> |
53 |
| - using indexed_types = adl_proof_t<basic_indexed_types, T...>; |
54 |
| - |
55 |
| - inline constexpr make_template_type_fn<indexed_types> make_indexed_types{}; |
| 56 | + template<std::size_t I, typename... T> |
| 57 | + using type_at = details::type_indexer::type<I, T...>; |
56 | 58 | }
|
57 | 59 |
|
58 | 60 | namespace stdsharp::details
|
59 | 61 | {
|
60 |
| - static constexpr struct indexed_piecewise_t |
61 |
| - { |
62 |
| - explicit indexed_piecewise_t() = default; |
63 |
| - } indexed_piecewise{}; |
| 62 | + template<typename...> |
| 63 | + struct indexed_values; |
64 | 64 |
|
65 |
| - template<typename T, std::size_t I> |
66 |
| - struct indexed_value : stdsharp::value_wrapper<T> |
| 65 | + template<typename... T, std::size_t... I> |
| 66 | + struct STDSHARP_EBO indexed_values<std::index_sequence<I...>, T...> : indexed_value<I, T>... |
67 | 67 | {
|
68 |
| - private: |
69 |
| - using m_base = stdsharp::value_wrapper<T>; |
| 68 | + static constexpr auto size() noexcept { return sizeof...(T); } |
70 | 69 |
|
71 |
| - public: |
72 |
| - using m_base::m_base; |
| 70 | + template<std::size_t J> |
| 71 | + using type = type_at<J, T...>; |
73 | 72 |
|
74 |
| - template<size_t... J, typename Tuple> |
75 |
| - requires std::constructible_from<m_base, get_element_t<J, Tuple>...> |
76 |
| - constexpr indexed_value( |
77 |
| - const std::index_sequence<J...> /*unused*/, |
78 |
| - const indexed_piecewise_t /*unused*/, |
79 |
| - Tuple&& tuple |
80 |
| - ) noexcept(nothrow_constructible_from<m_base, get_element_t<J, Tuple>...>): |
81 |
| - m_base(cpo::get_element<J>(cpp_forward(tuple))...) |
| 73 | + template<std::size_t J, typename Self, typename U = indexed_value<J, type<J>>> |
| 74 | + constexpr forward_cast_t<Self, type<J>> get(this Self&& self) noexcept |
82 | 75 | {
|
| 76 | + return forward_cast<Self, indexed_values, U>(self).get(); |
83 | 77 | }
|
84 |
| - }; |
85 | 78 |
|
86 |
| - template<typename... T> |
87 |
| - struct indexed_values |
88 |
| - { |
89 |
| - template<typename = index_sequence_for<T...>> |
90 |
| - struct impl; |
91 |
| - |
92 |
| - using indexed_types = stdsharp::indexed_types<T...>; |
93 |
| - |
94 |
| - template<std::size_t... I> |
95 |
| - struct STDSHARP_EBO impl<regular_value_sequence<I...>> : |
96 |
| - indexed_value<T, I>..., |
97 |
| - indexed_types |
| 79 | + template< |
| 80 | + std::size_t J, |
| 81 | + typename Self, |
| 82 | + typename SelfT = const Self, |
| 83 | + typename U = indexed_value<J, type<J>>> |
| 84 | + constexpr forward_cast_t<SelfT, type<J>> cget(this const Self&& self) noexcept |
98 | 85 | {
|
99 |
| - impl() = default; |
100 |
| - |
101 |
| - template<typename... U> |
102 |
| - requires(std::constructible_from<indexed_value<T, I>, U> && ...) |
103 |
| - constexpr impl(const indexed_piecewise_t /*unused*/, U&&... u) |
104 |
| - noexcept((nothrow_constructible_from<indexed_value<T, I>, U> && ...)): |
105 |
| - indexed_value<T, I>(cpp_forward(u))... |
106 |
| - { |
107 |
| - } |
108 |
| - |
109 |
| - template<typename... Tuple> |
110 |
| - requires( |
111 |
| - std::constructible_from< |
112 |
| - indexed_value<T, I>, |
113 |
| - std::make_index_sequence<std::tuple_size_v<Tuple>>, |
114 |
| - const indexed_piecewise_t&, |
115 |
| - Tuple> && |
116 |
| - ... |
117 |
| - ) |
118 |
| - explicit(sizeof...(Tuple) == 0) constexpr impl( |
119 |
| - const std::piecewise_construct_t /*unused*/, |
120 |
| - Tuple&&... tuples // |
121 |
| - ) |
122 |
| - noexcept( |
123 |
| - (nothrow_constructible_from< |
124 |
| - indexed_value<T, I>, |
125 |
| - std::make_index_sequence<std::tuple_size_v<Tuple>>, |
126 |
| - indexed_piecewise_t, |
127 |
| - Tuple> && |
128 |
| - ...) |
129 |
| - ): |
130 |
| - indexed_value<T, I>( |
131 |
| - std::make_index_sequence<std::tuple_size_v<Tuple>>{}, |
132 |
| - indexed_piecewise, |
133 |
| - cpp_forward(tuples) |
134 |
| - )... |
135 |
| - { |
136 |
| - } |
137 |
| - |
138 |
| - private: |
139 |
| - template<std::size_t J> |
140 |
| - using indexed_value_t = indexed_value<std::tuple_element_t<J, indexed_types>, J>; |
141 |
| - |
142 |
| - public: |
143 |
| - template<std::size_t J, typename Self> |
144 |
| - [[nodiscard]] constexpr decltype(auto) get(this Self&& self) noexcept |
145 |
| - { |
146 |
| - return forward_cast<Self, indexed_value_t<J>>(self).get(); |
147 |
| - } |
| 86 | + return forward_cast<SelfT, indexed_values, U>(self).get(); |
| 87 | + } |
148 | 88 |
|
149 |
| - template<std::size_t J, typename Self> |
150 |
| - [[nodiscard]] constexpr decltype(auto) cget(this Self&& self) noexcept |
151 |
| - { |
152 |
| - return forward_cast<Self, indexed_value_t<J>>(self).cget(); |
153 |
| - } |
154 |
| - }; |
| 89 | + template< |
| 90 | + std::size_t J, |
| 91 | + typename Self, |
| 92 | + typename SelfT = const Self&, |
| 93 | + typename U = indexed_value<J, type<J>>> |
| 94 | + constexpr forward_cast_t<SelfT, type<J>> cget(this const Self& self) noexcept |
| 95 | + { |
| 96 | + return forward_cast<SelfT, indexed_values, U>(self).get(); |
| 97 | + } |
155 | 98 | };
|
156 | 99 | }
|
157 | 100 |
|
158 | 101 | namespace stdsharp
|
159 | 102 | {
|
160 | 103 | template<typename... T>
|
161 |
| - struct indexed_values : details::indexed_values<T...>::template impl<> |
| 104 | + struct indexed_values : details::indexed_values<std::make_index_sequence<sizeof...(T)>, T...> |
162 | 105 | {
|
163 | 106 | private:
|
164 |
| - using m_indexed = details::indexed_values<T...>::template impl<>; |
| 107 | + using m_base = details::indexed_values<std::make_index_sequence<sizeof...(T)>, T...>; |
165 | 108 |
|
166 | 109 | public:
|
167 |
| - using m_indexed::m_indexed; |
168 |
| - |
169 | 110 | indexed_values() = default;
|
170 | 111 |
|
171 | 112 | template<typename... U>
|
172 |
| - explicit(sizeof...(U) == 1) constexpr indexed_values(U&&... u) |
173 |
| - noexcept(nothrow_constructible_from<m_indexed, details::indexed_piecewise_t, U...>) |
174 |
| - requires requires { |
175 |
| - requires std::constructible_from<m_indexed, details::indexed_piecewise_t, U...>; |
176 |
| - requires sizeof...(T) >= 1; |
177 |
| - requires(sizeof...(U) != 1) || |
178 |
| - !(std::same_as<std::remove_cvref_t<U>, indexed_values> && ...); |
179 |
| - } |
180 |
| - : m_indexed(details::indexed_piecewise_t{}, cpp_forward(u)...) |
| 113 | + requires list_initializable_from<m_base, U...> |
| 114 | + constexpr indexed_values(U&&... u) noexcept(nothrow_list_initializable_from<m_base, U...>): |
| 115 | + m_base{cpp_forward(u)...} |
181 | 116 | {
|
182 | 117 | }
|
183 | 118 | };
|
184 | 119 |
|
185 | 120 | template<typename... T>
|
186 | 121 | indexed_values(T&&...) -> indexed_values<std::decay_t<T>...>;
|
187 |
| - |
188 |
| - template<typename Indexed> |
189 |
| - using index_sequence_by = std::make_index_sequence<std::tuple_size_v<std::decay_t<Indexed>>>; |
190 |
| - |
191 |
| - inline constexpr struct indexed_apply_fn |
192 |
| - { |
193 |
| - private: |
194 |
| - template< |
195 |
| - std::size_t... I, |
196 |
| - typename Indexed, |
197 |
| - std::invocable<get_element_t<I, Indexed>...> Fn> |
198 |
| - static constexpr decltype(auto) impl( |
199 |
| - Fn&& fn, |
200 |
| - Indexed&& indexed, |
201 |
| - const std::index_sequence<I...> /*unused*/ |
202 |
| - ) noexcept(nothrow_invocable<Fn, get_element_t<I, Indexed>...>) |
203 |
| - { |
204 |
| - return invoke(cpp_forward(fn), cpo::get_element<I>(cpp_forward(indexed))...); |
205 |
| - } |
206 |
| - |
207 |
| - public: |
208 |
| - template<typename Indexed, typename Fn> |
209 |
| - requires requires { |
210 |
| - impl(std::declval<Fn>(), std::declval<Indexed>(), index_sequence_by<Indexed>{}); |
211 |
| - } |
212 |
| - constexpr decltype(auto) operator()(Fn&& fn, Indexed&& indexed) const noexcept( // |
213 |
| - noexcept( // |
214 |
| - impl(std::declval<Fn>(), std::declval<Indexed>(), index_sequence_by<Indexed>{}) |
215 |
| - ) |
216 |
| - ) |
217 |
| - { |
218 |
| - return impl(cpp_forward(fn), cpp_forward(indexed), index_sequence_by<Indexed>{}); |
219 |
| - } |
220 |
| - } indexed_apply{}; |
221 | 122 | }
|
222 | 123 |
|
223 | 124 | namespace std
|
224 | 125 | {
|
225 | 126 | template<typename... T>
|
226 |
| - struct tuple_size<::stdsharp::basic_indexed_types<T...>> : |
227 |
| - tuple_size<::stdsharp::regular_type_sequence<T...>> |
228 |
| - { |
229 |
| - }; |
230 |
| - |
231 |
| - template<::stdsharp::adl_proofed_for<::stdsharp::basic_indexed_types> T> |
232 |
| - struct tuple_size<T> : tuple_size<typename T::basic_indexed_types> |
233 |
| - { |
234 |
| - }; |
235 |
| - |
236 |
| - template<typename... T> |
237 |
| - struct tuple_size<::stdsharp::indexed_values<T...>> : |
238 |
| - tuple_size<::stdsharp::indexed_types<T...>> |
239 |
| - { |
240 |
| - }; |
241 |
| - |
242 |
| - template<std::size_t I, typename... T> |
243 |
| - struct tuple_element<I, ::stdsharp::basic_indexed_types<T...>> |
244 |
| - { |
245 |
| - using type = decltype( // |
246 |
| - ::stdsharp::basic_indexed_types<T...>{}.get_type(::stdsharp::index_constant<I>{}) |
247 |
| - )::type; |
248 |
| - }; |
249 |
| - |
250 |
| - template<std::size_t I, ::stdsharp::adl_proofed_for<::stdsharp::basic_indexed_types> T> |
251 |
| - struct tuple_element<I, T> : tuple_element<I, typename T::basic_indexed_types> |
| 127 | + struct tuple_size<::stdsharp::indexed_values<T...>> |
252 | 128 | {
|
| 129 | + static constexpr auto value = ::stdsharp::indexed_values<T...>::size(); |
253 | 130 | };
|
254 | 131 |
|
255 | 132 | template<std::size_t I, typename... T>
|
256 |
| - struct tuple_element<I, ::stdsharp::indexed_values<T...>> : |
257 |
| - tuple_element<I, ::stdsharp::indexed_types<T...>> |
| 133 | + struct tuple_element<I, ::stdsharp::indexed_values<T...>> |
258 | 134 | {
|
| 135 | + using type = ::stdsharp::indexed_values<T...>::template type<I>; |
259 | 136 | };
|
260 | 137 | }
|
261 | 138 |
|
|
0 commit comments