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#define VIR_HAVE_STRUCT_REFLECT 1
25 using std::remove_cvref_t;
29 template <
typename Struct>
30 struct anything_but_base_of
32 anything_but_base_of() =
default;
34 anything_but_base_of(
const anything_but_base_of&) =
delete;
37 requires (not std::is_base_of_v<T, Struct>)
41 template <
typename Struct>
42 struct any_empty_base_of
45 requires (std::is_base_of_v<T, Struct> and std::is_empty_v<T>)
49 template <
typename T,
size_t... Indexes>
50 concept brace_constructible_impl
51 =
requires { T{{((void)Indexes, anything_but_base_of<T>())}...}; }
54 T{any_empty_base_of<T>(), {((void)Indexes, anything_but_base_of<T>())}...};
58 T{any_empty_base_of<T>(), any_empty_base_of<T>(),
59 {((void)Indexes, anything_but_base_of<T>())}...};
63 T{any_empty_base_of<T>(), any_empty_base_of<T>(), any_empty_base_of<T>(),
64 {((void)Indexes, anything_but_base_of<T>())}...};
67 template <
typename T,
size_t N>
68 concept aggregate_with_n_members = []<
size_t... Is>(std::index_sequence<Is...>) {
69 return brace_constructible_impl<T, Is...>;
70 }(std::make_index_sequence<N>());
72 template <
typename T,
size_t Lo = 0,
size_t Hi = sizeof(T) * CHAR_BIT,
size_t N = 8>
76 constexpr size_t left_index = Lo + (N - Lo) / 2;
77 constexpr size_t right_index = N + (Hi - N + 1) / 2;
78 if constexpr (aggregate_with_n_members<T, N>)
80 if constexpr (N == Hi)
85 constexpr size_t right = struct_size<T, N + 1, Hi, right_index>();
86 if constexpr (right == 0)
94 else if constexpr (N == Lo)
96 if constexpr (N == Hi)
101 return struct_size<T, N + 1, Hi, right_index>();
105 constexpr size_t left = struct_size<T, Lo, N - 1, left_index>();
106 if constexpr (left > 0)
109 else if constexpr (N == Hi)
115 return struct_size<T, N + 1, Hi, right_index>();
120 template <
size_t Total>
123 template <
typename T>
124 struct remove_ref_in_tuple;
126 template <
typename... Ts>
127 struct remove_ref_in_tuple<std::tuple<Ts...>>
128 {
using type = std::tuple<std::remove_reference_t<Ts>...>; };
130 template <
typename T1,
typename T2>
131 struct remove_ref_in_tuple<std::pair<T1, T2>>
132 {
using type = std::pair<std::remove_reference_t<T1>, std::remove_reference_t<T2>>; };
137 template <
typename T>
138 constexpr std::tuple<>
142 template <
typename T>
143 constexpr std::tuple<>
151 template <
typename T>
156 return std::forward_as_tuple(a);
159 template <
typename T>
162 ->
typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
164 const auto &[a] = obj;
168 template <
size_t N,
typename T>
169 constexpr const auto &
172 static_assert(N == 0);
177 template <
size_t N,
typename T>
181 static_assert(N == 0);
190 template <
typename T>
195 return std::forward_as_tuple(a, b);
198 template <
typename T>
201 ->
typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
203 const auto &[a, b] = obj;
207 template <
typename T>
212 return std::pair<decltype((a)), decltype((b))>(a, b);
215 template <
typename T>
218 ->
typename remove_ref_in_tuple<decltype(to_pair_ref(std::declval<T>()))>::type
220 const auto &[a, b] = obj;
224 template <
size_t N,
typename T>
228 static_assert(N < 2);
230 return std::get<N>(std::forward_as_tuple(a, b));
234#define VIR_STRUCT_GET_(size_, ...) \
236 struct struct_get<size_> \
238 template <typename T> \
240 to_tuple_ref(T &&obj) \
242 auto &&[__VA_ARGS__] = obj; \
243 return std::forward_as_tuple(__VA_ARGS__); \
246 template <typename T> \
248 to_tuple(const T &obj) \
249 -> typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type \
251 const auto &[__VA_ARGS__] = obj; \
252 return {__VA_ARGS__}; \
255 template <size_t N, typename T> \
259 static_assert(N < size_); \
260 auto &&[__VA_ARGS__] = obj; \
261 return std::get<N>(std::forward_as_tuple(__VA_ARGS__)); \
264 VIR_STRUCT_GET_(3, x0, x1, x2);
265 VIR_STRUCT_GET_(4, x0, x1, x2, x3);
266 VIR_STRUCT_GET_(5, x0, x1, x2, x3, x4);
267 VIR_STRUCT_GET_(6, x0, x1, x2, x3, x4, x5);
268 VIR_STRUCT_GET_(7, x0, x1, x2, x3, x4, x5, x6);
269 VIR_STRUCT_GET_(8, x0, x1, x2, x3, x4, x5, x6, x7);
270 VIR_STRUCT_GET_(9, x0, x1, x2, x3, x4, x5, x6, x7, x8);
271 VIR_STRUCT_GET_(10, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9);
272 VIR_STRUCT_GET_(11, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10);
273 VIR_STRUCT_GET_(12, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11);
274 VIR_STRUCT_GET_(13, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12);
275 VIR_STRUCT_GET_(14, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13);
276 VIR_STRUCT_GET_(15, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14);
277 VIR_STRUCT_GET_(16, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15);
278 VIR_STRUCT_GET_(17, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
280 VIR_STRUCT_GET_(18, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
282 VIR_STRUCT_GET_(19, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
284 VIR_STRUCT_GET_(20, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
286 VIR_STRUCT_GET_(21, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
287 x16, x17, x18, x19, x20);
288 VIR_STRUCT_GET_(22, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
289 x16, x17, x18, x19, x20, x21);
290 VIR_STRUCT_GET_(23, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
291 x16, x17, x18, x19, x20, x21, x22);
292 VIR_STRUCT_GET_(24, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
293 x16, x17, x18, x19, x20, x21, x22, x23);
294 VIR_STRUCT_GET_(25, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
295 x16, x17, x18, x19, x20, x21, x22, x23, x24);
296 VIR_STRUCT_GET_(26, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
297 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25);
298 VIR_STRUCT_GET_(27, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
299 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26);
300 VIR_STRUCT_GET_(28, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
301 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27);
302 VIR_STRUCT_GET_(29, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
303 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28);
304 VIR_STRUCT_GET_(30, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
305 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29);
306 VIR_STRUCT_GET_(31, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
307 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29,
309 VIR_STRUCT_GET_(32, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
310 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
312 VIR_STRUCT_GET_(33, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
313 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
315 VIR_STRUCT_GET_(34, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
316 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
318 VIR_STRUCT_GET_(35, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
319 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
321 VIR_STRUCT_GET_(36, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
322 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
323 x31, x32, x33, x34, x35);
324 VIR_STRUCT_GET_(37, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
325 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
326 x31, x32, x33, x34, x35, x36);
327 VIR_STRUCT_GET_(38, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
328 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
329 x31, x32, x33, x34, x35, x36, x37);
330 VIR_STRUCT_GET_(39, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
331 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
332 x31, x32, x33, x34, x35, x36, x37, x38);
333 VIR_STRUCT_GET_(40, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
334 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
335 x31, x32, x33, x34, x35, x36, x37, x38, x39);
336 VIR_STRUCT_GET_(41, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
337 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
338 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40);
339 VIR_STRUCT_GET_(42, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
340 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
341 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41);
342 VIR_STRUCT_GET_(43, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
343 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
344 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42);
345 VIR_STRUCT_GET_(44, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
346 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
347 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43);
348 VIR_STRUCT_GET_(45, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
349 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
350 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44);
351 VIR_STRUCT_GET_(46, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
352 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
353 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44,
355 VIR_STRUCT_GET_(47, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
356 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
357 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
359 VIR_STRUCT_GET_(48, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
360 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
361 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
363 VIR_STRUCT_GET_(49, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
364 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
365 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
367 VIR_STRUCT_GET_(50, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
368 x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30,
369 x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45,
371#undef VIR_STRUCT_GET_
374 template <
typename T>
375 concept has_tuple_size
376 =
requires(T x, std::tuple_size<T> ts) { {
static_cast<int>(ts)} -> std::same_as<int>; };
378 template <
typename T>
379 concept aggregate_without_tuple_size
380 = std::is_aggregate_v<T> and not has_tuple_size<T>
381 and
requires (
const T& x) { detail::struct_size<T>(); };
384 template <
typename From,
typename To>
387 using From2 = std::remove_reference_t<From>;
388 using with_const = std::conditional_t<std::is_const_v<From2>,
const To, To>;
390 = std::conditional_t<std::is_volatile_v<From2>,
volatile with_const, with_const>;
391 using type = std::conditional_t<std::is_lvalue_reference_v<From>, with_volatile &,
392 std::conditional_t<std::is_rvalue_reference_v<From>,
393 with_volatile &&, with_volatile>>;
404 template <
typename T>
406 or detail::aggregate_without_tuple_size<std::remove_cvref_t<T>>;
423 template <
typename T>
424 requires (detail::aggregate_without_tuple_size<T> or detail::has_tuple_size<T>)
427 template <detail::aggregate_without_tuple_size T>
430 template <detail::has_tuple_size T>
436 template <std::
size_t N, reflectable_struct T>
437 requires (N < struct_size_v<std::remove_cvref_t<T>>)
438 constexpr decltype(
auto)
441 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>()
442 .
template get<N>(std::forward<T>(obj));
445 template <std::
size_t N, reflectable_struct T>
446 struct struct_element
448 using type = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
455 template <std::
size_t N, reflectable_struct T>
457 = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
462 template <reflectable_struct T>
466 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().
to_tuple(
467 std::forward<T>(obj));
473 template <reflectable_struct T>
477 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().
to_tuple_ref(
478 std::forward<T>(obj));
485 template <reflectable_struct T>
487 : detail::copy_cvref<
488 T, decltype(detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().to_tuple(
495 template <
typename T>
496 using as_tuple_t =
typename as_tuple<T>::type;
501 template <
typename T>
505 {
return detail::struct_get<2>().to_pair(std::forward<T>(obj)); }
510 template <
typename T>
514 {
return detail::struct_get<2>().to_pair_ref(std::forward<T>(obj)); }
520 template <
typename T>
529 template <
typename T>
530 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:405
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:512
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:529
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:456
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:439
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:474
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:503
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:495
constexpr std::size_t struct_size_v
The number of non-static data members of T.
Definition struct_reflect.h:425
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:463
Defines the member type type to a std::pair specialization matching the non-static data members of T.
Definition struct_reflect.h:523
Defines the member type type to a std::tuple specialization matching the non-static data members of T...
Definition struct_reflect.h:489