vir-simd 0.4.189
Parallelism TS 2 extensions and simd fallback implementation
Loading...
Searching...
No Matches
struct_reflect.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-3.0-or-later */
2/* Copyright © 2018–2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
3 * Matthias Kretz <m.kretz@gsi.de>
4 */
5
6#ifndef VIR_STRUCT_SIZE_H_
7#define VIR_STRUCT_SIZE_H_
8
12
13#if defined DOXYGEN \
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
17#include <utility>
18#include <tuple>
19#include <climits>
20
21namespace vir
22{
24 namespace detail
25 {
26 using std::remove_cvref_t;
27 using std::size_t;
28
29 // struct_size implementation
30 template <typename Struct>
31 struct anything_but_base_of
32 {
33 anything_but_base_of() = default;
34
35 anything_but_base_of(const anything_but_base_of&) = delete;
36
37 template <typename T>
38 requires (not std::is_base_of_v<T, Struct>)
39 operator T&() const&;
40 };
41
42 template <typename Struct>
43 struct any_empty_base_of
44 {
45 template <typename T>
46 requires (std::is_base_of_v<T, Struct> and std::is_empty_v<T>)
47 operator T();
48 };
49
50 template <typename T, size_t... Indexes>
51 concept brace_constructible_impl
52 = requires { T{{((void)Indexes, anything_but_base_of<T>())}...}; }
53 or requires
54 {
55 T{any_empty_base_of<T>(), {((void)Indexes, anything_but_base_of<T>())}...};
56 }
57 or requires
58 {
59 T{any_empty_base_of<T>(), any_empty_base_of<T>(),
60 {((void)Indexes, anything_but_base_of<T>())}...};
61 }
62 or requires
63 {
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>())}...};
66 };
67
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>());
72
73 template <typename T, size_t Lo = 0, size_t Hi = sizeof(T) * CHAR_BIT, size_t N = 8>
74 constexpr size_t
75 struct_size()
76 {
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>) // N is a valid size
80 {
81 if constexpr (N == Hi)
82 // we found the best valid size inside [Lo, Hi]
83 return N;
84 else
85 { // there may be a larger size in [N+1, Hi]
86 constexpr size_t right = struct_size<T, N + 1, Hi, right_index>();
87 if constexpr (right == 0)
88 // no, there isn't
89 return N;
90 else
91 // yes, there is
92 return right;
93 }
94 }
95 else if constexpr (N == Lo)
96 { // we can only look for a valid size in [N+1, Hi]
97 if constexpr (N == Hi)
98 // but [N+1, Hi] is empty
99 return 0; // no valid size found
100 else
101 // [N+1, Hi] is non-empty
102 return struct_size<T, N + 1, Hi, right_index>();
103 }
104 else
105 { // the answer could be in [Lo, N-1] or [N+1, Hi]
106 constexpr size_t left = struct_size<T, Lo, N - 1, left_index>();
107 if constexpr (left > 0)
108 // valid size in [Lo, N-1] => there can't be a valid size in [N+1, Hi] anymore
109 return left;
110 else if constexpr (N == Hi)
111 // [N+1, Hi] is empty => [Lo, Hi] has no valid size
112 return 0;
113 else
114 // there can only be a valid size in [N+1, Hi], if there is none the
115 // recursion returns 0 anyway
116 return struct_size<T, N + 1, Hi, right_index>();
117 }
118 }
119
120 // struct_get implementation
121 template <size_t Total>
122 struct struct_get;
123
124 template <typename T>
125 struct remove_ref_in_tuple;
126
127 template <typename... Ts>
128 struct remove_ref_in_tuple<std::tuple<Ts...>>
129 { using type = std::tuple<std::remove_reference_t<Ts>...>; };
130
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>>; };
134
135 template <>
136 struct struct_get<0>
137 {
138 template <typename T>
139 constexpr std::tuple<>
140 to_tuple_ref(T &&)
141 { return {}; }
142
143 template <typename T>
144 constexpr std::tuple<>
145 to_tuple(const T &)
146 { return {}; }
147 };
148
149 template <>
150 struct struct_get<1>
151 {
152 template <typename T>
153 constexpr auto
154 to_tuple_ref(T &&obj)
155 {
156 auto && [a] = obj;
157 return std::forward_as_tuple(a);
158 }
159
160 template <typename T>
161 constexpr auto
162 to_tuple(const T &obj)
163 -> typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
164 {
165 const auto &[a] = obj;
166 return {a};
167 }
168
169 template <size_t N, typename T>
170 constexpr const auto &
171 get(const T &obj)
172 {
173 static_assert(N == 0);
174 auto && [a] = obj;
175 return a;
176 }
177
178 template <size_t N, typename T>
179 constexpr auto &
180 get(T &obj)
181 {
182 static_assert(N == 0);
183 auto && [a] = obj;
184 return a;
185 }
186 };
187
188 template <>
189 struct struct_get<2>
190 {
191 template <typename T>
192 constexpr auto
193 to_tuple_ref(T &&obj)
194 {
195 auto &&[a, b] = obj;
196 return std::forward_as_tuple(a, b);
197 }
198
199 template <typename T>
200 constexpr auto
201 to_tuple(const T &obj)
202 -> typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type
203 {
204 const auto &[a, b] = obj;
205 return {a, b};
206 }
207
208 template <typename T>
209 constexpr auto
210 to_pair_ref(T &&obj)
211 {
212 auto &&[a, b] = obj;
213 return std::pair<decltype((a)), decltype((b))>(a, b);
214 }
215
216 template <typename T>
217 constexpr auto
218 to_pair(const T &obj)
219 -> typename remove_ref_in_tuple<decltype(to_pair_ref(std::declval<T>()))>::type
220 {
221 const auto &[a, b] = obj;
222 return {a, b};
223 }
224
225 template <size_t N, typename T>
226 constexpr auto &
227 get(T &&obj)
228 {
229 static_assert(N < 2);
230 auto &&[a, b] = obj;
231 return std::get<N>(std::forward_as_tuple(a, b));
232 }
233 };
234
235#define VIR_STRUCT_GET_(size_, ...) \
236 template <> \
237 struct struct_get<size_> \
238 { \
239 template <typename T> \
240 constexpr auto \
241 to_tuple_ref(T &&obj) \
242 { \
243 auto &&[__VA_ARGS__] = obj; \
244 return std::forward_as_tuple(__VA_ARGS__); \
245 } \
246 \
247 template <typename T> \
248 constexpr auto \
249 to_tuple(const T &obj) \
250 -> typename remove_ref_in_tuple<decltype(to_tuple_ref(std::declval<T>()))>::type \
251 { \
252 const auto &[__VA_ARGS__] = obj; \
253 return {__VA_ARGS__}; \
254 } \
255 \
256 template <size_t N, typename T> \
257 constexpr auto & \
258 get(T &&obj) \
259 { \
260 static_assert(N < size_); \
261 auto &&[__VA_ARGS__] = obj; \
262 return std::get<N>(std::forward_as_tuple(__VA_ARGS__)); \
263 } \
264 }
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,
280 x16);
281 VIR_STRUCT_GET_(18, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
282 x16, x17);
283 VIR_STRUCT_GET_(19, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
284 x16, x17, x18);
285 VIR_STRUCT_GET_(20, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15,
286 x16, x17, x18, x19);
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,
309 x30);
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,
312 x31);
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,
315 x31, x32);
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,
318 x31, x32, x33);
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,
321 x31, x32, x33, x34);
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,
355 x45);
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,
359 x46);
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,
363 x46, x47);
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,
367 x46, x47, x48);
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,
371 x46, x47, x48, x49);
372#undef VIR_STRUCT_GET_
373
374 // concept definitions
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>; };
378
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>(); };
383
384 // traits
385 template <typename From, typename To>
386 struct copy_cvref
387 {
388 using From2 = std::remove_reference_t<From>;
389 using with_const = std::conditional_t<std::is_const_v<From2>, const To, To>;
390 using with_volatile
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>>;
395 };
396 } // namespace detail
397
405 template <typename T>
406 concept reflectable_struct = detail::has_tuple_size<std::remove_cvref_t<T>>
407 or detail::aggregate_without_tuple_size<std::remove_cvref_t<T>>;
408
424 template <typename T>
425 requires (detail::aggregate_without_tuple_size<T> or detail::has_tuple_size<T>)
426 constexpr inline std::size_t struct_size_v = 0;
427
428 template <detail::aggregate_without_tuple_size T>
429 constexpr inline std::size_t struct_size_v<T> = detail::struct_size<T>();
430
431 template <detail::has_tuple_size T>
432 constexpr inline std::size_t struct_size_v<T> = std::tuple_size_v<T>;
433
437 template <std::size_t N, reflectable_struct T>
438 requires (N < struct_size_v<std::remove_cvref_t<T>>)
439 constexpr decltype(auto)
440 struct_get(T &&obj)
441 {
442 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>()
443 .template get<N>(std::forward<T>(obj));
444 }
445
446 template <std::size_t N, reflectable_struct T>
447 struct struct_element
448 {
449 using type = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
450 };
451
456 template <std::size_t N, reflectable_struct T>
458 = std::remove_reference_t<decltype(struct_get<N>(std::declval<T &>()))>;
459
463 template <reflectable_struct T>
464 constexpr auto
465 to_tuple(T &&obj)
466 {
467 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().to_tuple(
468 std::forward<T>(obj));
469 }
470
474 template <reflectable_struct T>
475 constexpr auto
476 to_tuple_ref(T &&obj)
477 {
478 return detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().to_tuple_ref(
479 std::forward<T>(obj));
480 }
481
486 template <reflectable_struct T>
487 struct as_tuple
488 : detail::copy_cvref<
489 T, decltype(detail::struct_get<struct_size_v<std::remove_cvref_t<T>>>().to_tuple(
490 std::declval<T>()))>
491 {};
492
496 template <typename T>
497 using as_tuple_t = typename as_tuple<T>::type;
498
502 template <typename T>
504 constexpr auto
505 to_pair(T &&obj)
506 { return detail::struct_get<2>().to_pair(std::forward<T>(obj)); }
507
511 template <typename T>
513 constexpr auto
514 to_pair_ref(T &&obj)
515 { return detail::struct_get<2>().to_pair_ref(std::forward<T>(obj)); }
516
521 template <typename T>
523 struct as_pair
524 : detail::copy_cvref<T, decltype(detail::struct_get<2>().to_pair(std::declval<T>()))>
525 {};
526
530 template <typename T>
531 using as_pair_t = typename as_pair<T>::type;
532
533} // namespace vir
534
535#endif // work around broken Clang
536#endif // structured bindings & concepts
537#endif // VIR_STRUCT_SIZE_H_
538
539// vim: noet cc=101 tw=100 sw=2 ts=8
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