Project
Loading...
Searching...
No Matches
StructToTuple.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11#ifndef O2_FRAMEWORK_STRUCTTOTUPLE_H_
12#define O2_FRAMEWORK_STRUCTTOTUPLE_H_
13
14#include <Framework/Traits.h>
15#include <array>
16
17// Structured binding packs (P1061) are C++26, but clang implements them as an
18// extension in every language mode and advertises them via the feature test
19// macro, so we can use them while still compiling as C++20.
20#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 202411L
21#define DPL_STRUCTURED_BINDING_PACKS 1
22#endif
23
24#ifndef DPL_STRUCTURED_BINDING_PACKS
25namespace
26{
27template <class T, typename... Args>
28decltype(void(T{std::declval<Args>()...}), std::true_type())
29 brace_test(int);
30
31template <class T, typename... Args>
32std::false_type
33 brace_test(...);
34} // namespace
35#endif
36
37namespace o2::framework
38{
39#ifndef DPL_STRUCTURED_BINDING_PACKS
40struct any_type {
41 template <class T>
42 constexpr operator T(); // non explicit
43};
44
45template <class T, typename... Args>
46struct is_braces_constructible : decltype(brace_test<T, Args...>(0)) {
47};
48#endif
49
51 template <typename T>
52 operator T()
53 {
54 }
55};
56
57template <typename T>
58consteval auto brace_constructible_size(auto... Members)
59{
60 if constexpr (requires { T{Members...}; } == false) {
61 static_assert(sizeof...(Members) != 0, "You need to make sure that you have implicit constructors or that you call the explicit constructor correctly.");
62 return sizeof...(Members) - 1;
63 } else {
64 return brace_constructible_size<T>(Members..., UniversalType{});
65 }
66}
67
68template <bool B, typename T>
70{
71 using type = std::decay_t<T>;
72 constexpr int nesting = B ? 1 : 0;
73 return brace_constructible_size<type>() - nesting;
74}
75
79template <bool B, typename T>
81{
82#ifdef DPL_STRUCTURED_BINDING_PACKS
83 return 0;
84#else
85 return nested_brace_constructible_size<B, T>() / 10;
86#endif
87}
88
89#ifdef DPL_STRUCTURED_BINDING_PACKS
90#ifdef __clang__
91#pragma clang diagnostic push
92#pragma clang diagnostic ignored "-Wc++26-extensions"
93#endif
94template <bool B = false, class T, int D = 0, typename L>
95constexpr auto homogeneous_apply_refs(L l, T&& object)
96{
97 auto&& [... members] = object;
98 if constexpr (sizeof...(members) == 0) {
99 return std::array<bool, 0>();
100 } else {
101 return std::array{l(members)...};
102 }
103}
104#ifdef __clang__
105#pragma clang diagnostic pop
106#endif
107
108#else // DPL_STRUCTURED_BINDING_PACKS
109
110#define DPL_ENUM_0(pre, post)
111#define DPL_ENUM_1(pre, post) pre##0##post
112#define DPL_ENUM_2(pre, post) pre##0##post, pre##1##post
113#define DPL_ENUM_3(pre, post) pre##0##post, pre##1##post, pre##2##post
114#define DPL_ENUM_4(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post
115#define DPL_ENUM_5(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post
116#define DPL_ENUM_6(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post, pre##5##post
117#define DPL_ENUM_7(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post, pre##5##post, pre##6##post
118#define DPL_ENUM_8(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post, pre##5##post, pre##6##post, pre##7##post
119#define DPL_ENUM_9(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post, pre##5##post, pre##6##post, pre##7##post, pre##8##post
120#define DPL_ENUM_10(pre, post) pre##0##post, pre##1##post, pre##2##post, pre##3##post, pre##4##post, pre##5##post, pre##6##post, pre##7##post, pre##8##post, pre##9##post
121
122#define DPL_ENUM_20(pre, post) DPL_ENUM_10(pre, post), DPL_ENUM_10(pre##1, post)
123#define DPL_ENUM_30(pre, post) DPL_ENUM_20(pre, post), DPL_ENUM_10(pre##2, post)
124#define DPL_ENUM_40(pre, post) DPL_ENUM_30(pre, post), DPL_ENUM_10(pre##3, post)
125#define DPL_ENUM_50(pre, post) DPL_ENUM_40(pre, post), DPL_ENUM_10(pre##4, post)
126#define DPL_ENUM_60(pre, post) DPL_ENUM_50(pre, post), DPL_ENUM_10(pre##5, post)
127#define DPL_ENUM_70(pre, post) DPL_ENUM_60(pre, post), DPL_ENUM_10(pre##6, post)
128#define DPL_ENUM_80(pre, post) DPL_ENUM_70(pre, post), DPL_ENUM_10(pre##7, post)
129#define DPL_ENUM_90(pre, post) DPL_ENUM_80(pre, post), DPL_ENUM_10(pre##8, post)
130#define DPL_ENUM_100(pre, post) DPL_ENUM_90(pre, post), DPL_ENUM_10(pre##9, post)
131
132#define DPL_ENUM(pre, post, d, u) DPL_ENUM_##d##0(pre, post), DPL_ENUM_##u(pre##d, post)
133
134#define DPL_FENUM_0(f, pre, post)
135#define DPL_FENUM_1(f, pre, post) f(pre##0##post)
136#define DPL_FENUM_2(f, pre, post) f(pre##0##post), f(pre##1##post)
137#define DPL_FENUM_3(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post)
138#define DPL_FENUM_4(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post)
139#define DPL_FENUM_5(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post)
140#define DPL_FENUM_6(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post), f(pre##5##post)
141#define DPL_FENUM_7(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post), f(pre##5##post), f(pre##6##post)
142#define DPL_FENUM_8(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post), f(pre##5##post), f(pre##6##post), f(pre##7##post)
143#define DPL_FENUM_9(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post), f(pre##5##post), f(pre##6##post), f(pre##7##post), f(pre##8##post)
144#define DPL_FENUM_10(f, pre, post) f(pre##0##post), f(pre##1##post), f(pre##2##post), f(pre##3##post), f(pre##4##post), f(pre##5##post), f(pre##6##post), f(pre##7##post), f(pre##8##post), f(pre##9##post)
145
146#define DPL_FENUM_20(f, pre, post) DPL_FENUM_10(f, pre, post), DPL_FENUM_10(f, pre##1, post)
147#define DPL_FENUM_30(f, pre, post) DPL_FENUM_20(f, pre, post), DPL_FENUM_10(f, pre##2, post)
148#define DPL_FENUM_40(f, pre, post) DPL_FENUM_30(f, pre, post), DPL_FENUM_10(f, pre##3, post)
149#define DPL_FENUM_50(f, pre, post) DPL_FENUM_40(f, pre, post), DPL_FENUM_10(f, pre##4, post)
150#define DPL_FENUM_60(f, pre, post) DPL_FENUM_50(f, pre, post), DPL_FENUM_10(f, pre##5, post)
151#define DPL_FENUM_70(f, pre, post) DPL_FENUM_60(f, pre, post), DPL_FENUM_10(f, pre##6, post)
152#define DPL_FENUM_80(f, pre, post) DPL_FENUM_70(f, pre, post), DPL_FENUM_10(f, pre##7, post)
153#define DPL_FENUM_90(f, pre, post) DPL_FENUM_80(f, pre, post), DPL_FENUM_10(f, pre##8, post)
154#define DPL_FENUM_100(f, pre, post) DPL_FENUM_90(f, pre, post), DPL_FENUM_10(f, pre##9, post)
155
156#define DPL_FENUM(f, pre, post, d, u) DPL_FENUM_##d##0(f, pre, post), DPL_FENUM_##u(f, pre##d, post)
157
158#define DPL_HOMOGENEOUS_APPLY_ENTRY_LOW(u) \
159 constexpr(numElements == u) \
160 { \
161 auto&& [DPL_ENUM_##u(p, )] = object; \
162 return std::array<decltype(l(p0)), u>{DPL_FENUM_##u(l, p, )}; \
163 }
164
165#define DPL_HOMOGENEOUS_APPLY_ENTRY(d, u) \
166 constexpr(numElements == d##u) \
167 { \
168 auto&& [DPL_ENUM(p, , d, u)] = object; \
169 return std::array<decltype(l(p0)), d##u>{DPL_FENUM(l, p, , d, u)}; \
170 }
171
172#define DPL_HOMOGENEOUS_APPLY_ENTRY_TENS(d) \
173 constexpr(numElements == d##0) \
174 { \
175 auto&& [DPL_ENUM_##d##0(p, )] = object; \
176 return std::array<decltype(l(p0)), d##0>{DPL_FENUM_##d##0(l, p, )}; \
177 }
178
179template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
180 requires(D == 9)
181constexpr auto homogeneous_apply_refs(L l, T&& object)
182{
183 constexpr int numElements = nested_brace_constructible_size<B, T>();
184 // clang-format off
186 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 8)
187 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 7)
188 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 6)
189 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 5)
190 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 4)
191 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 3)
192 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 2)
193 else if DPL_HOMOGENEOUS_APPLY_ENTRY (9, 1)
195 else { return std::array<bool,0>(); }
196 // clang-format on
197}
198
199template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
200 requires(D == 8)
201constexpr auto homogeneous_apply_refs(L l, T&& object)
202{
203 constexpr int numElements = nested_brace_constructible_size<B, T>();
204 // clang-format off
206 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 8)
207 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 7)
208 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 6)
209 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 5)
210 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 4)
211 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 3)
212 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 2)
213 else if DPL_HOMOGENEOUS_APPLY_ENTRY (8, 1)
215 else { return std::array<bool,0>(); }
216 // clang-format on
217}
218
219template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
220 requires(D == 7)
221constexpr auto homogeneous_apply_refs(L l, T&& object)
222{
223 constexpr int numElements = nested_brace_constructible_size<B, T>();
224 // clang-format off
226 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 8)
227 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 7)
228 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 6)
229 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 5)
230 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 4)
231 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 3)
232 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 2)
233 else if DPL_HOMOGENEOUS_APPLY_ENTRY (7, 1)
235 else { return std::array<bool,0>(); }
236 // clang-format on
237}
238
239template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
240 requires(D == 6)
241constexpr auto homogeneous_apply_refs(L l, T&& object)
242{
243 constexpr int numElements = nested_brace_constructible_size<B, T>();
244 // clang-format off
246 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 8)
247 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 7)
248 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 6)
249 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 5)
250 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 4)
251 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 3)
252 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 2)
253 else if DPL_HOMOGENEOUS_APPLY_ENTRY (6, 1)
255 else { return std::array<bool,0>(); }
256 // clang-format on
257}
258
259template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
260 requires(D == 5)
261constexpr auto homogeneous_apply_refs(L l, T&& object)
262{
263 constexpr int numElements = nested_brace_constructible_size<B, T>();
264 // clang-format off
266 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 8)
267 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 7)
268 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 6)
269 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 5)
270 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 4)
271 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 3)
272 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 2)
273 else if DPL_HOMOGENEOUS_APPLY_ENTRY (5, 1)
275 else { return std::array<bool,0>(); }
276 // clang-format on
277}
278
279template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
280 requires(D == 4)
281constexpr auto homogeneous_apply_refs(L l, T&& object)
282{
283 constexpr int numElements = nested_brace_constructible_size<B, T>();
284 // clang-format off
286 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 8)
287 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 7)
288 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 6)
289 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 5)
290 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 4)
291 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 3)
292 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 2)
293 else if DPL_HOMOGENEOUS_APPLY_ENTRY (4, 1)
295 else { return std::array<bool,0>(); }
296 // clang-format on
297}
298
299template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
300 requires(D == 3)
301constexpr auto homogeneous_apply_refs(L l, T&& object)
302{
303 constexpr int numElements = nested_brace_constructible_size<B, T>();
304 // clang-format off
306 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 8)
307 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 7)
308 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 6)
309 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 5)
310 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 4)
311 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 3)
312 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 2)
313 else if DPL_HOMOGENEOUS_APPLY_ENTRY (3, 1)
315 else { return std::array<bool,0>(); }
316 // clang-format on
317}
318
319template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
320 requires(D == 2)
321constexpr auto homogeneous_apply_refs(L l, T&& object)
322{
323 constexpr int numElements = nested_brace_constructible_size<B, T>();
324 // clang-format off
326 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 8)
327 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 7)
328 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 6)
329 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 5)
330 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 4)
331 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 3)
332 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 2)
333 else if DPL_HOMOGENEOUS_APPLY_ENTRY (2, 1)
335 else { return std::array<bool,0>(); }
336 // clang-format on
337}
338
339template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
340 requires(D == 1)
341constexpr auto homogeneous_apply_refs(L l, T&& object)
342{
343 constexpr int numElements = nested_brace_constructible_size<B, T>();
344 // clang-format off
346 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 8)
347 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 7)
348 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 6)
349 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 5)
350 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 4)
351 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 3)
352 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 2)
353 else if DPL_HOMOGENEOUS_APPLY_ENTRY (1, 1)
355 else { return std::array<bool,0>(); }
356 // clang-format on
357}
358
359template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
360 requires(D == 0)
361constexpr auto homogeneous_apply_refs(L l, T&& object)
362{
363 constexpr int numElements = nested_brace_constructible_size<B, T>();
364 // clang-format off
374 else { return std::array<bool,0>(); }
375 // clang-format on
376}
377
378#endif // DPL_STRUCTURED_BINDING_PACKS
379
380template <int D, typename T, typename L>
381constexpr auto homogeneous_apply_refs_sized(L l, T&& object)
382{
383 return homogeneous_apply_refs<false, T, D, L>(l, object);
384}
385
386} // namespace o2::framework
387
388#endif // O2_FRAMEWORK_STRUCTTOTUPLE_H_
bounded_vector< int > members
#define DPL_HOMOGENEOUS_APPLY_ENTRY_TENS(d)
#define DPL_HOMOGENEOUS_APPLY_ENTRY(d, u)
#define DPL_HOMOGENEOUS_APPLY_ENTRY_LOW(u)
Definition B.h:16
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint object
Definition glcorearb.h:4041
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
consteval int homogeneous_apply_refs_size()
consteval int nested_brace_constructible_size()
consteval auto brace_constructible_size(auto... Members)
constexpr auto homogeneous_apply_refs_sized(L l, T &&object)
constexpr auto homogeneous_apply_refs(L l, T &&object)