2#include "gaia/config/config.h"
8#include "gaia/core/utility.h"
13 GAIA_MSVC_WARNING_PUSH()
21 GAIA_MSVC_WARNING_DISABLE(4702)
28 constexpr operator T();
31 template <
typename T,
typename... TArgs>
32 decltype((void)T{std::declval<TArgs>()...}, std::true_type{}) is_braces_constructible(
int);
34 template <
typename,
typename...>
35 std::false_type is_braces_constructible(...);
37 template <
typename T,
typename... TArgs>
38 using is_braces_constructible_t =
decltype(detail::is_braces_constructible<T, TArgs...>(0));
52 template <
typename S,
size_t... Is,
typename Tuple>
53 GAIA_NODISCARD S tuple_to_struct(std::index_sequence<Is...> , Tuple&& tup) {
54 return {std::get<Is>(GAIA_FWD(tup))...};
62 template <
typename S,
typename Tuple>
63 GAIA_NODISCARD S tuple_to_struct(Tuple&& tup) {
64 using T = std::remove_reference_t<Tuple>;
66 return tuple_to_struct<S>(std::make_index_sequence<std::tuple_size<T>{}>{}, GAIA_FWD(tup));
74 static constexpr uint32_t StructToTupleMaxTypes_Bits = 4;
76 static constexpr uint32_t StructToTupleMaxTypes = (1 << StructToTupleMaxTypes_Bits) - 1;
83 auto struct_to_tuple(T&&
object)
noexcept {
84 using type = core::raw_t<T>;
86 if constexpr (std::is_empty_v<type>) {
87 return std::make_tuple();
89 detail::is_braces_constructible_t<
90 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
91 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
92 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
93 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15] = GAIA_FWD(
object);
94 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
96 detail::is_braces_constructible_t<
97 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
98 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
99 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
100 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14] = GAIA_FWD(
object);
101 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
102 }
else if constexpr (
103 detail::is_braces_constructible_t<
104 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
105 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
106 detail::any_type, detail::any_type, detail::any_type>{}) {
107 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13] = GAIA_FWD(
object);
108 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
109 }
else if constexpr (
110 detail::is_braces_constructible_t<
111 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
112 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
113 detail::any_type, detail::any_type>{}) {
114 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12] = GAIA_FWD(
object);
115 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
116 }
else if constexpr (
117 detail::is_braces_constructible_t<
118 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
119 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
120 detail::any_type>{}) {
121 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] = GAIA_FWD(
object);
122 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
123 }
else if constexpr (
124 detail::is_braces_constructible_t<
125 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
126 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
127 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10] = GAIA_FWD(
object);
128 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
129 }
else if constexpr (
130 detail::is_braces_constructible_t<
131 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
132 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
133 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9] = GAIA_FWD(
object);
134 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9);
135 }
else if constexpr (
136 detail::is_braces_constructible_t<
137 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
138 detail::any_type, detail::any_type, detail::any_type>{}) {
139 auto&& [p1, p2, p3, p4, p5, p6, p7, p8] = GAIA_FWD(
object);
140 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8);
141 }
else if constexpr (
142 detail::is_braces_constructible_t<
143 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
144 detail::any_type, detail::any_type>{}) {
145 auto&& [p1, p2, p3, p4, p5, p6, p7] = GAIA_FWD(
object);
146 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7);
147 }
else if constexpr (
148 detail::is_braces_constructible_t<
149 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
150 detail::any_type>{}) {
151 auto&& [p1, p2, p3, p4, p5, p6] = GAIA_FWD(
object);
152 return std::make_tuple(p1, p2, p3, p4, p5, p6);
153 }
else if constexpr (
154 detail::is_braces_constructible_t<
155 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
156 auto&& [p1, p2, p3, p4, p5] = GAIA_FWD(
object);
157 return std::make_tuple(p1, p2, p3, p4, p5);
158 }
else if constexpr (
159 detail::is_braces_constructible_t<
160 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
161 auto&& [p1, p2, p3, p4] = GAIA_FWD(
object);
162 return std::make_tuple(p1, p2, p3, p4);
163 }
else if constexpr (
164 detail::is_braces_constructible_t<type, detail::any_type, detail::any_type, detail::any_type>{}) {
165 auto&& [p1, p2, p3] = GAIA_FWD(
object);
166 return std::make_tuple(p1, p2, p3);
167 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
168 auto&& [p1, p2] = GAIA_FWD(
object);
169 return std::make_tuple(p1, p2);
170 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
171 auto&& [p1] = GAIA_FWD(
object);
172 return std::make_tuple(p1);
175 GAIA_ASSERT2(
false,
"Unsupported number of members");
185 template <
typename T>
186 auto struct_member_count() {
187 using type = core::raw_t<T>;
189 if constexpr (std::is_empty_v<type>) {
191 }
else if constexpr (
192 detail::is_braces_constructible_t<
193 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
194 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
195 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
197 }
else if constexpr (
198 detail::is_braces_constructible_t<
199 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
200 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
201 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
203 }
else if constexpr (
204 detail::is_braces_constructible_t<
205 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
206 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
207 detail::any_type, detail::any_type, detail::any_type>{}) {
209 }
else if constexpr (
210 detail::is_braces_constructible_t<
211 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
212 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
213 detail::any_type, detail::any_type>{}) {
215 }
else if constexpr (
216 detail::is_braces_constructible_t<
217 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
218 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
219 detail::any_type>{}) {
221 }
else if constexpr (
222 detail::is_braces_constructible_t<
223 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
224 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
226 }
else if constexpr (
227 detail::is_braces_constructible_t<
228 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
229 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
231 }
else if constexpr (
232 detail::is_braces_constructible_t<
233 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
234 detail::any_type, detail::any_type, detail::any_type>{}) {
236 }
else if constexpr (
237 detail::is_braces_constructible_t<
238 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
239 detail::any_type, detail::any_type>{}) {
241 }
else if constexpr (
242 detail::is_braces_constructible_t<
243 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
244 detail::any_type>{}) {
246 }
else if constexpr (
247 detail::is_braces_constructible_t<
248 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
250 }
else if constexpr (
251 detail::is_braces_constructible_t<
252 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
254 }
else if constexpr (
255 detail::is_braces_constructible_t<type, detail::any_type, detail::any_type, detail::any_type>{}) {
257 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
259 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
263 GAIA_ASSERT2(
false,
"Unsupported number of members");
272 template <
typename T,
typename Func>
273 auto each_member(T&&
object, Func&& visitor) {
274 using type = core::raw_t<T>;
276 if constexpr (std::is_empty_v<type>) {
278 }
else if constexpr (
279 detail::is_braces_constructible_t<
280 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
281 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
282 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
283 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15] = object;
284 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
285 }
else if constexpr (
286 detail::is_braces_constructible_t<
287 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
288 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
289 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
290 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14] = object;
291 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
292 }
else if constexpr (
293 detail::is_braces_constructible_t<
294 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
295 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
296 detail::any_type, detail::any_type, detail::any_type>{}) {
297 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13] = object;
298 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
299 }
else if constexpr (
300 detail::is_braces_constructible_t<
301 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
302 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
303 detail::any_type, detail::any_type>{}) {
304 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12] = object;
305 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
306 }
else if constexpr (
307 detail::is_braces_constructible_t<
308 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
309 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
310 detail::any_type>{}) {
311 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] = object;
312 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
313 }
else if constexpr (
314 detail::is_braces_constructible_t<
315 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
316 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
317 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10] = object;
318 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
319 }
else if constexpr (
320 detail::is_braces_constructible_t<
321 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
322 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
323 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9] = object;
324 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9);
325 }
else if constexpr (
326 detail::is_braces_constructible_t<
327 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
328 detail::any_type, detail::any_type, detail::any_type>{}) {
329 auto&& [p1, p2, p3, p4, p5, p6, p7, p8] = object;
330 return visitor(p1, p2, p3, p4, p5, p6, p7, p8);
331 }
else if constexpr (
332 detail::is_braces_constructible_t<
333 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
334 detail::any_type, detail::any_type>{}) {
335 auto&& [p1, p2, p3, p4, p5, p6, p7] = object;
336 return visitor(p1, p2, p3, p4, p5, p6, p7);
337 }
else if constexpr (
338 detail::is_braces_constructible_t<
339 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
340 detail::any_type>{}) {
341 auto&& [p1, p2, p3, p4, p5, p6] = object;
342 return visitor(p1, p2, p3, p4, p5, p6);
343 }
else if constexpr (
344 detail::is_braces_constructible_t<
345 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
346 auto&& [p1, p2, p3, p4, p5] = object;
347 return visitor(p1, p2, p3, p4, p5);
348 }
else if constexpr (
349 detail::is_braces_constructible_t<
350 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
351 auto&& [p1, p2, p3, p4] = object;
352 return visitor(p1, p2, p3, p4);
353 }
else if constexpr (
354 detail::is_braces_constructible_t<type, detail::any_type, detail::any_type, detail::any_type>{}) {
355 auto&& [p1, p2, p3] = object;
356 return visitor(p1, p2, p3);
357 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
358 auto&& [p1, p2] = object;
359 return visitor(p1, p2);
360 }
else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
361 auto&& [p1] = object;
365 GAIA_ASSERT2(
false,
"Unsupported number of members");
368 GAIA_MSVC_WARNING_POP()