6#ifndef VIR_STRUCT_SIZE_H_
7#define VIR_STRUCT_SIZE_H_
14 or (defined __cpp_structured_bindings && defined __cpp_concepts && __cpp_concepts >= 201907)
15#if !__cpp_lib_tuple_like || !defined __clang__ || __clang_major__ != 17
16#define VIR_HAVE_STRUCT_REFLECT 1
26 using std::remove_cvref_t;
30 template <
typename Struct>
31 struct anything_but_base_of
33 anything_but_base_of() =
default;
35 anything_but_base_of(
const anything_but_base_of&) =
delete;
38 requires (not std::is_base_of_v<T, Struct>)
42 template <
typename Struct>
43 struct any_empty_base_of
46 requires (std::is_base_of_v<T, Struct> and std::is_empty_v<T>)
50 template <
typename T,
size_t... Indexes>
51 concept brace_constructible_impl
52 =
requires { T{{((void)Indexes, anything_but_base_of<T>())}...}; }
55 T{any_empty_base_of<T>(), {((void)Indexes, anything_but_base_of<T>())}...};
59 T{any_empty_base_of<T>(), any_empty_base_of<T>(),
60 {((void)Indexes, anything_but_base_of<T>())}...};
64 T{any_empty_base_of<T>(), any_empty_base_of<T>(), any_empty_base_of<T>(),
65 {((void)Indexes, anything_but_base_of<T>())}...};
68 template <
typename T,
size_t N>
69 concept aggregate_with_n_members = []<
size_t... Is>(std::index_sequence<Is...>) {
70 return brace_constructible_impl<T, Is...>;
71 }(std::make_index_sequence<N>());
73 template <
typename T,
size_t Lo = 0,
size_t Hi = sizeof(T) * CHAR_BIT,
size_t N = 8>
77 constexpr size_t left_index = Lo + (N - Lo) / 2;
78 constexpr size_t right_index = N + (Hi - N + 1) / 2;
79 if constexpr (aggregate_with_n_members<T, N>)
81 if constexpr (N == Hi)
86 constexpr size_t right = struct_size<T, N + 1, Hi, right_index>();
87 if constexpr (right == 0)
95 else if constexpr (N == Lo)
97 if constexpr (N == Hi)
102 return struct_size<T, N + 1, Hi, right_index>();
106 constexpr size_t left = struct_size<T, Lo, N - 1, left_index>();
107 if constexpr (left > 0)
110 else if constexpr (N == Hi)
116 return struct_size<T, N + 1, Hi, right_index>();
121 template <
size_t Total>
124 template <
typename T>
125 struct remove_ref_in_tuple;
127 template <
typename... Ts>
128 struct remove_ref_in_tuple<std::tuple<Ts...>>
129 {
using type = std::tuple<std::remove_reference_t<Ts>...>; };
131 template <
typename T1,
typename T2>
132 struct remove_ref_in_tuple<std::pair<T1, T2>>
133 {
using type = std::pair<std::remove_reference_t<T1>, std::remove_reference_t<T2>>; };
138 template <
typename T>
139 constexpr std::tuple<>
143 template <
typename T>
144 constexpr std::tuple<>
152 template <
typename T>
157 return std::forward_as_tuple(a);
160 template <
typename T>
163 ->
typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
165 const auto &[a] = obj;
169 template <
size_t N,
typename T>
170 constexpr const auto &
173 static_assert(N == 0);
178 template <
size_t N,
typename T>
182 static_assert(N == 0);
191 template <
typename T>
196 return std::forward_as_tuple(a, b);
199 template <
typename T>
202 ->
typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
204 const auto &[a, b] = obj;
208 template <
typename T>
213 return std::pair<decltype((a)), decltype((b))>(a, b);
216 template <
typename T>
219 ->
typename remove_ref_in_tuple<decltype(to_pair_ref(std::declval<T>()))>::type
221 const auto &[a, b] = obj;
225 template <
size_t N,
typename T>
229 static_assert(N < 2);
231 return std::get<N>(std::forward_as_tuple(a, b));
235#define VIR_STRUCT_GET_(size_, ...) \
237 struct struct_get<size_> \
239 template <typename T> \
241 to_tuple_ref(T &&obj) \
243 auto &&[__VA_ARGS__] = obj; \
244 return std::forward_as_tuple(__VA_ARGS__); \
247 template <typename T> \
249 to_tuple(const T &obj) \
250 -> typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type \
252 const auto &[__VA_ARGS__] = obj; \
253 return {__VA_ARGS__}; \
256 template <size_t N, typename T> \
260 static_assert(N < size_); \
261 auto &&[__VA_ARGS__] = obj; \
262 return std::get<N>(std::forward_as_tuple(__VA_ARGS__)); \
265 VIR_STRUCT_GET_(3, x0, x1, x2);
266 VIR_STRUCT_GET_(4, x0, x1, x2, x3);
267 VIR_STRUCT_GET_(5, x0, x1, x2, x3, x4);
268 VIR_STRUCT_GET_(6, x0, x1, x2, x3, x4, x5);
269 VIR_STRUCT_GET_(7, x0, x1, x2, x3, x4, x5, x6);
270 VIR_STRUCT_GET_(8, x0, x1, x2, x3, x4, x5, x6, x7);
271 VIR_STRUCT_GET_(9, x0, x1, x2, x3, x4, x5, x6, x7, x8);
272 VIR_STRUCT_GET_(10, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9);
273 VIR_STRUCT_GET_(11, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10);
274 VIR_STRUCT_GET_(12, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11);
275 VIR_STRUCT_GET_(13, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12);
276 VIR_STRUCT_GET_(14, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13);
277 VIR_STRUCT_GET_(15, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14);
278 VIR_STRUCT_GET_(16, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15);
279 VIR_STRUCT_GET_(17, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
281 VIR_STRUCT_GET_(18, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
283 VIR_STRUCT_GET_(19, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
285 VIR_STRUCT_GET_(20, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
287 VIR_STRUCT_GET_(21, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
288 x16, x17, x18, x19, x20);
289 VIR_STRUCT_GET_(22, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
290 x16, x17, x18, x19, x20, x21);
291 VIR_STRUCT_GET_(23, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
292 x16, x17, x18, x19, x20, x21, x22);
293 VIR_STRUCT_GET_(24, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
294 x16, x17, x18, x19, x20, x21, x22, x23);
295 VIR_STRUCT_GET_(25, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
296 x16, x17, x18, x19, x20, x21, x22, x23, x24);
297 VIR_STRUCT_GET_(26, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
298 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25);
299 VIR_STRUCT_GET_(27, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
300 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26);
301 VIR_STRUCT_GET_(28, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
302 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27);
303 VIR_STRUCT_GET_(29, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
304 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28);
305 VIR_STRUCT_GET_(30, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
306 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29);
307 VIR_STRUCT_GET_(31, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
308 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29,
310 VIR_STRUCT_GET_(32, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
311 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
313 VIR_STRUCT_GET_(33, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
314 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
316 VIR_STRUCT_GET_(34, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
317 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
319 VIR_STRUCT_GET_(35, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
320 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
322 VIR_STRUCT_GET_(36, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
323 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
324 x31, x32, x33, x34, x35);
325 VIR_STRUCT_GET_(37, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
326 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
327 x31, x32, x33, x34, x35, x36);
328 VIR_STRUCT_GET_(38, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
329 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
330 x31, x32, x33, x34, x35, x36, x37);
331 VIR_STRUCT_GET_(39, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
332 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
333 x31, x32, x33, x34, x35, x36, x37, x38);
334 VIR_STRUCT_GET_(40, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
335 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
336 x31, x32, x33, x34, x35, x36, x37, x38, x39);
337 VIR_STRUCT_GET_(41, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
338 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
339 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40);
340 VIR_STRUCT_GET_(42, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
341 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
342 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41);
343 VIR_STRUCT_GET_(43, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
344 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
345 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42);
346 VIR_STRUCT_GET_(44, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
347 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
348 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43);
349 VIR_STRUCT_GET_(45, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
350 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
351 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44);
352 VIR_STRUCT_GET_(46, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
353 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
354 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44,
356 VIR_STRUCT_GET_(47, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
357 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
358 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
360 VIR_STRUCT_GET_(48, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
361 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
362 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
364 VIR_STRUCT_GET_(49, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
365 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
366 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
368 VIR_STRUCT_GET_(50, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
369 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
370 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
372#undef VIR_STRUCT_GET_
375 template <
typename T>
376 concept has_tuple_size
377 =
requires(T x, std::tuple_size<T> ts) { {
static_cast<int>(ts)} -> std::same_as<int>; };
379 template <
typename T>
380 concept aggregate_without_tuple_size
381 = std::is_aggregate_v<T> and not has_tuple_size<T>
382 and
requires (
const T& x) { detail::struct_size<T>(); };
385 template <
typename From,
typename To>
388 using From2 = std::remove_reference_t<From>;
389 using with_const = std::conditional_t<std::is_const_v<From2>,
const To, To>;
391 = std::conditional_t<std::is_volatile_v<From2>,
volatile with_const, with_const>;
392 using type = std::conditional_t<std::is_lvalue_reference_v<From>, with_volatile &,
393 std::conditional_t<std::is_rvalue_reference_v<From>,
394 with_volatile &&, with_volatile>>;
405 template <
typename T>
407 or detail::aggregate_without_tuple_size<std::remove_cvref_t<T>>;
424 template <
typename T>
425 requires (detail::aggregate_without_tuple_size<T> or detail::has_tuple_size<T>)
428 template <detail::aggregate_without_tuple_size T>
431 template <detail::has_tuple_size T>
437 template <std::
size_t N, reflectable_struct T>
438 requires (N < struct_size_v<std::remove_cvref_t<T>>)
439 constexpr decltype(
auto)
442 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>()
443 .
template get<N>(std::forward<T>(obj));
446 template <std::
size_t N, reflectable_struct T>
447 struct struct_element
449 using type = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
456 template <std::
size_t N, reflectable_struct T>
458 = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
463 template <reflectable_struct T>
467 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().
to_tuple(
468 std::forward<T>(obj));
474 template <reflectable_struct T>
478 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().
to_tuple_ref(
479 std::forward<T>(obj));
486 template <reflectable_struct T>
488 : detail::copy_cvref<
489 T, decltype(detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().to_tuple(
496 template <
typename T>
497 using as_tuple_t =
typename as_tuple<T>::type;
502 template <
typename T>
506 {
return detail::struct_get<2>().to_pair(std::forward<T>(obj)); }
511 template <
typename T>
515 {
return detail::struct_get<2>().to_pair_ref(std::forward<T>(obj)); }
521 template <
typename T>
530 template <
typename T>
531 using as_pair_t =
typename as_pair<T>::type;
Satisfied if T can be used with the following functions and types.
Definition struct_reflect.h:406
This namespace collects libraries and tools authored by Matthias Kretz.
Definition constexpr_wrapper.h:21
constexpr auto to_pair_ref(T &&obj)
Returns a std::pair of lvalue references to all the non-static data members of obj.
Definition struct_reflect.h:513
typename as_pair< T >::type as_pair_t
Alias for a std::pair specialization matching the non-static data members of T.
Definition struct_reflect.h:530
std::remove_reference_t< decltype(struct_get< N >(std::declval< T & >()))> struct_element_t
struct_element_t<N, T> is an alias for the type of the N -th non-static data member of T.
Definition struct_reflect.h:457
constexpr decltype(auto) struct_get(T &&obj)
Returns a cv-qualified reference to the N -th non-static data member in obj.
Definition struct_reflect.h:440
constexpr auto to_tuple_ref(T &&obj)
Returns a std::tuple of lvalue references to all the non-static data members of obj.
Definition struct_reflect.h:475
constexpr auto to_pair(T &&obj)
Returns a std::pair with a copy of all the non-static data members of obj.
Definition struct_reflect.h:504
constexpr decltype(auto) get(const simd_tuple< T, N > &tup)
Definition simdize.h:504
typename as_tuple< T >::type as_tuple_t
Alias for a std::tuple specialization matching the non-static data members of T.
Definition struct_reflect.h:496
constexpr std::size_t struct_size_v
The number of non-static data members of T.
Definition struct_reflect.h:426
constexpr auto to_tuple(T &&obj)
Returns a std::tuple with a copy of all the non-static data members of obj.
Definition struct_reflect.h:464
Defines the member type type to a std::pair specialization matching the non-static data members of T.
Definition struct_reflect.h:524
Defines the member type type to a std::tuple specialization matching the non-static data members of T...
Definition struct_reflect.h:490