1 #ifndef DONUT_REFLECTION_HPP
2 #define DONUT_REFLECTION_HPP
18 template <std::
size_t Index>
19 struct AggregateSizeTag : AggregateSizeTag<Index - 1> {};
22 struct AggregateSizeTag<0> {};
25 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<26>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 26; }
26 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<25>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 25; }
27 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<24>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 24; }
28 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<23>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 23; }
29 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<22>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 22; }
30 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<21>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 21; }
31 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<20>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 20; }
32 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<19>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 19; }
33 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<18>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 18; }
34 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<17>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 17; }
35 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<16>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 16; }
36 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<15>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 15; }
37 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<14>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 14; }
38 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<13>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 13; }
39 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<12>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 12; }
40 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<11>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 11; }
41 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag<10>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 10; }
42 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 9>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 9; }
43 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 8>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 8; }
44 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 7>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 7; }
45 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 6>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 6; }
46 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 5>) -> decltype(T{Init{}, Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 5; }
47 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 4>) -> decltype(T{Init{}, Init{}, Init{}, Init{}}, std::size_t{}) {
return 4; }
48 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 3>) -> decltype(T{Init{}, Init{}, Init{}}, std::size_t{}) {
return 3; }
49 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 2>) -> decltype(T{Init{}, Init{}}, std::size_t{}) {
return 2; }
50 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 1>) -> decltype(T{Init{}}, std::size_t{}) {
return 1; }
51 template <
typename T> constexpr
auto aggregateSizeImpl(AggregateSizeTag< 0>) -> decltype(T{}, std::size_t{}) {
return 0; }
58 requires std::is_aggregate_v<T>
59 struct aggregate_size : std::integral_constant<std::size_t, detail::aggregateSizeImpl<T>(detail::AggregateSizeTag<26>{})> {};
86 [[nodiscard]] constexpr
auto fields(
auto&& aggregate) noexcept {
87 using T = std::remove_cvref_t<decltype(aggregate)>;
88 static_assert(std::is_aggregate_v<T>);
89 constexpr std::size_t FIELD_COUNT = aggregate_size_v<T>;
90 if constexpr (FIELD_COUNT == 26) {
91 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] = aggregate;
92 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z);
93 }
else if constexpr (FIELD_COUNT == 25) {
94 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y] = aggregate;
95 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y);
96 }
else if constexpr (FIELD_COUNT == 24) {
97 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x] = aggregate;
98 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x);
99 }
else if constexpr (FIELD_COUNT == 23) {
100 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w] = aggregate;
101 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w);
102 }
else if constexpr (FIELD_COUNT == 22) {
103 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v] = aggregate;
104 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v);
105 }
else if constexpr (FIELD_COUNT == 21) {
106 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u] = aggregate;
107 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u);
108 }
else if constexpr (FIELD_COUNT == 20) {
109 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t] = aggregate;
110 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t);
111 }
else if constexpr (FIELD_COUNT == 19) {
112 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = aggregate;
113 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
114 }
else if constexpr (FIELD_COUNT == 18) {
115 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r] = aggregate;
116 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q, r);
117 }
else if constexpr (FIELD_COUNT == 17) {
118 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q] = aggregate;
119 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p, q);
120 }
else if constexpr (FIELD_COUNT == 16) {
121 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p] = aggregate;
122 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o, p);
123 }
else if constexpr (FIELD_COUNT == 15) {
124 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o] = aggregate;
125 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n, o);
126 }
else if constexpr (FIELD_COUNT == 14) {
127 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m, n] = aggregate;
128 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m, n);
129 }
else if constexpr (FIELD_COUNT == 13) {
130 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l, m] = aggregate;
131 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l, m);
132 }
else if constexpr (FIELD_COUNT == 12) {
133 auto&& [a, b, c, d,
e, f, g, h, i, j, k, l] = aggregate;
134 return std::tie(a, b, c, d,
e, f, g, h, i, j, k, l);
135 }
else if constexpr (FIELD_COUNT == 11) {
136 auto&& [a, b, c, d,
e, f, g, h, i, j, k] = aggregate;
137 return std::tie(a, b, c, d,
e, f, g, h, i, j, k);
138 }
else if constexpr (FIELD_COUNT == 10) {
139 auto&& [a, b, c, d,
e, f, g, h, i, j] = aggregate;
140 return std::tie(a, b, c, d,
e, f, g, h, i, j);
141 }
else if constexpr (FIELD_COUNT == 9) {
142 auto&& [a, b, c, d,
e, f, g, h, i] = aggregate;
143 return std::tie(a, b, c, d,
e, f, g, h, i);
144 }
else if constexpr (FIELD_COUNT == 8) {
145 auto&& [a, b, c, d,
e, f, g, h] = aggregate;
146 return std::tie(a, b, c, d,
e, f, g, h);
147 }
else if constexpr (FIELD_COUNT == 7) {
148 auto&& [a, b, c, d,
e, f, g] = aggregate;
149 return std::tie(a, b, c, d,
e, f, g);
150 }
else if constexpr (FIELD_COUNT == 6) {
151 auto&& [a, b, c, d,
e, f] = aggregate;
152 return std::tie(a, b, c, d,
e, f);
153 }
else if constexpr (FIELD_COUNT == 5) {
154 auto&& [a, b, c, d,
e] = aggregate;
155 return std::tie(a, b, c, d,
e);
156 }
else if constexpr (FIELD_COUNT == 4) {
157 auto&& [a, b, c, d] = aggregate;
158 return std::tie(a, b, c, d);
159 }
else if constexpr (FIELD_COUNT == 3) {
160 auto&& [a, b, c] = aggregate;
161 return std::tie(a, b, c);
162 }
else if constexpr (FIELD_COUNT == 2) {
163 auto&& [a, b] = aggregate;
164 return std::tie(a, b);
165 }
else if constexpr (FIELD_COUNT == 1) {
166 auto&& [a] = aggregate;
188 template <std::
size_t N>
190 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) ->
void {
191 (fn(std::integral_constant<std::size_t, Indices>{}), ...);
192 }(std::make_index_sequence<N>{});
207 constexpr
void forEach(
auto&& tuple,
auto fn) {
208 [&]<std::size_t... Indices>(std::index_sequence<Indices...>) {
209 (fn(std::get<Indices>(tuple)), ...);
210 }(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<decltype(tuple)>>>{});
226 [[nodiscard]] constexpr
auto transform(
auto&& tuple,
auto fn) {
227 return [&]<std::size_t... Indices>(std::index_sequence<Indices...>) {
228 return std::make_tuple(fn(std::get<Indices>(tuple))...);
229 }(std::make_index_sequence<std::tuple_size_v<std::remove_cvref_t<decltype(tuple)>>>{});
constexpr float e
Definition: math.hpp:34
Definition: utilities.hpp:142
constexpr auto transform(auto &&tuple, auto fn)
Execute a function for each element in a given tuple and return a tuple containing the results.
Definition: reflection.hpp:226
constexpr auto fields(auto &&aggregate) noexcept
Get a tuple of references to each of the fields of an aggregate.
Definition: reflection.hpp:86
constexpr void forEachIndex(auto fn)
Execute a function once for each index in the sequence from 0 up to, but not including,...
Definition: reflection.hpp:189
constexpr void forEach(auto &&tuple, auto fn)
Execute a function once for each element in a given tuple, sequentially.
Definition: reflection.hpp:207
constexpr std::size_t aggregate_size_v
The number of fields in a given aggregate type.
Definition: reflection.hpp:72