Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
reflection.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <tuple>
5#include <type_traits>
6#include <utility>
7
8#include "gaia/core/utility.h"
9
10namespace gaia {
11 namespace meta {
12
13 GAIA_MSVC_WARNING_PUSH()
14 // Fix for MSVC bug:
15 // ...
16 // template <DataLayout TDataLayout, typename ValueType>
17 // struct data_view_policy_soa {
18 // static_assert(std::is_copy_assignable_v<ValueType>);
19 // using TTuple = decltype(meta::struct_to_tuple(std::declval<ValueType>())); << unreachable code
20 // ...
21 GAIA_MSVC_WARNING_DISABLE(4702) // unreachable code
22
23 namespace detail {
24 // Check if type T is constructible via T{Args...}
25 struct any_type {
26 template <typename T>
27 constexpr operator T(); // non explicit
28 };
29
30 template <typename T, typename... TArgs>
31 decltype((void)T{std::declval<TArgs>()...}, std::true_type{}) is_braces_constructible(int);
32
33 template <typename, typename...>
34 std::false_type is_braces_constructible(...);
35
36 template <typename T, typename... TArgs>
37 using is_braces_constructible_t = decltype(detail::is_braces_constructible<T, TArgs...>(0));
38 } // namespace detail
39
40 //----------------------------------------------------------------------
41 // Tuple to struct conversion
42 //----------------------------------------------------------------------
43
44 template <typename S, size_t... Is, typename Tuple>
45 GAIA_NODISCARD S tuple_to_struct(std::index_sequence<Is...> /*no_name*/, Tuple&& tup) {
46 return {std::get<Is>(GAIA_FWD(tup))...};
47 }
48
49 template <typename S, typename Tuple>
50 GAIA_NODISCARD S tuple_to_struct(Tuple&& tup) {
51 using T = std::remove_reference_t<Tuple>;
52
53 return tuple_to_struct<S>(std::make_index_sequence<std::tuple_size<T>{}>{}, GAIA_FWD(tup));
54 }
55
56 //----------------------------------------------------------------------
57 // Struct to tuple conversion
58 //----------------------------------------------------------------------
59
61 static constexpr uint32_t StructToTupleMaxTypes_Bits = 4;
62 static constexpr uint32_t StructToTupleMaxTypes = (1 << StructToTupleMaxTypes_Bits) - 1;
63
65 template <typename T>
66 auto struct_to_tuple(T&& object) noexcept {
67 using type = core::raw_t<T>;
68
69 if constexpr (std::is_empty_v<type>) {
70 return std::make_tuple();
71 } else if constexpr (detail::is_braces_constructible_t<
72 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
73 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
74 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
75 detail::any_type>{}) {
76 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15] = GAIA_FWD(object);
77 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
78 } else if constexpr (detail::is_braces_constructible_t<
79 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
80 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
81 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
82 detail::any_type>{}) {
83 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14] = GAIA_FWD(object);
84 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
85 } else if constexpr (detail::is_braces_constructible_t<
86 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
87 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
88 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
89 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13] = GAIA_FWD(object);
90 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
91 } else if constexpr (detail::is_braces_constructible_t<
92 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
93 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
94 detail::any_type, detail::any_type, detail::any_type>{}) {
95 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12] = GAIA_FWD(object);
96 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
97 } else if constexpr (detail::is_braces_constructible_t<
98 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
99 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
100 detail::any_type, detail::any_type>{}) {
101 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] = GAIA_FWD(object);
102 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
103 } else if constexpr (detail::is_braces_constructible_t<
104 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
105 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
106 detail::any_type>{}) {
107 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10] = GAIA_FWD(object);
108 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
109 } else if constexpr (detail::is_braces_constructible_t<
110 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
111 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
112 detail::any_type>{}) {
113 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9] = GAIA_FWD(object);
114 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8, p9);
115 } else if constexpr (detail::is_braces_constructible_t<
116 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
117 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
118 auto&& [p1, p2, p3, p4, p5, p6, p7, p8] = GAIA_FWD(object);
119 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7, p8);
120 } else if constexpr (detail::is_braces_constructible_t<
121 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
122 detail::any_type, detail::any_type, detail::any_type>{}) {
123 auto&& [p1, p2, p3, p4, p5, p6, p7] = GAIA_FWD(object);
124 return std::make_tuple(p1, p2, p3, p4, p5, p6, p7);
125 } else if constexpr (detail::is_braces_constructible_t<
126 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
127 detail::any_type, detail::any_type>{}) {
128 auto&& [p1, p2, p3, p4, p5, p6] = GAIA_FWD(object);
129 return std::make_tuple(p1, p2, p3, p4, p5, p6);
130 } else if constexpr (detail::is_braces_constructible_t<
131 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
132 detail::any_type>{}) {
133 auto&& [p1, p2, p3, p4, p5] = GAIA_FWD(object);
134 return std::make_tuple(p1, p2, p3, p4, p5);
135 } else if constexpr (detail::is_braces_constructible_t<
136 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
137 auto&& [p1, p2, p3, p4] = GAIA_FWD(object);
138 return std::make_tuple(p1, p2, p3, p4);
139 } else if constexpr (detail::is_braces_constructible_t<
140 type, detail::any_type, detail::any_type, detail::any_type>{}) {
141 auto&& [p1, p2, p3] = GAIA_FWD(object);
142 return std::make_tuple(p1, p2, p3);
143 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
144 auto&& [p1, p2] = GAIA_FWD(object);
145 return std::make_tuple(p1, p2);
146 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
147 auto&& [p1] = GAIA_FWD(object);
148 return std::make_tuple(p1);
149 }
150
151 GAIA_ASSERT2(false, "Unsupported number of members");
152 }
153
154 //----------------------------------------------------------------------
155 // Struct to tuple conversion
156 //----------------------------------------------------------------------
157
158 template <typename T>
159 auto struct_member_count() {
160 using type = core::raw_t<T>;
161
162 if constexpr (std::is_empty_v<type>) {
163 return 0;
164 } else if constexpr (detail::is_braces_constructible_t<
165 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
166 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
167 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
168 detail::any_type>{}) {
169 return 15;
170 } else if constexpr (detail::is_braces_constructible_t<
171 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
172 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
173 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
174 detail::any_type>{}) {
175 return 14;
176 } else if constexpr (detail::is_braces_constructible_t<
177 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
178 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
179 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
180 return 13;
181 } else if constexpr (detail::is_braces_constructible_t<
182 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
183 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
184 detail::any_type, detail::any_type, detail::any_type>{}) {
185 return 12;
186 } else if constexpr (detail::is_braces_constructible_t<
187 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
188 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
189 detail::any_type, detail::any_type>{}) {
190 return 11;
191 } else if constexpr (detail::is_braces_constructible_t<
192 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
193 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
194 detail::any_type>{}) {
195 return 10;
196 } else if constexpr (detail::is_braces_constructible_t<
197 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
198 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
199 detail::any_type>{}) {
200 return 9;
201 } else if constexpr (detail::is_braces_constructible_t<
202 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
203 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
204 return 8;
205 } else if constexpr (detail::is_braces_constructible_t<
206 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
207 detail::any_type, detail::any_type, detail::any_type>{}) {
208 return 7;
209 } else if constexpr (detail::is_braces_constructible_t<
210 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
211 detail::any_type, detail::any_type>{}) {
212 return 6;
213 } else if constexpr (detail::is_braces_constructible_t<
214 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
215 detail::any_type>{}) {
216 return 5;
217 } else if constexpr (detail::is_braces_constructible_t<
218 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
219 return 4;
220 } else if constexpr (detail::is_braces_constructible_t<
221 type, detail::any_type, detail::any_type, detail::any_type>{}) {
222 return 3;
223 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
224 return 2;
225 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
226 return 1;
227 }
228
229 GAIA_ASSERT2(false, "Unsupported number of members");
230 }
231
232 template <typename T, typename Func>
233 auto each_member(T&& object, Func&& visitor) {
234 using type = core::raw_t<T>;
235
236 if constexpr (std::is_empty_v<type>) {
237 visitor();
238 } else if constexpr (detail::is_braces_constructible_t<
239 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
240 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
241 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
242 detail::any_type>{}) {
243 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15] = object;
244 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15);
245 } else if constexpr (detail::is_braces_constructible_t<
246 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
247 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
248 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
249 detail::any_type>{}) {
250 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14] = object;
251 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14);
252 } else if constexpr (detail::is_braces_constructible_t<
253 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
254 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
255 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
256 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13] = object;
257 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13);
258 } else if constexpr (detail::is_braces_constructible_t<
259 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
260 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
261 detail::any_type, detail::any_type, detail::any_type>{}) {
262 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12] = object;
263 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12);
264 } else if constexpr (detail::is_braces_constructible_t<
265 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
266 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
267 detail::any_type, detail::any_type>{}) {
268 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11] = object;
269 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
270 } else if constexpr (detail::is_braces_constructible_t<
271 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
272 detail::any_type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
273 detail::any_type>{}) {
274 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10] = object;
275 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
276 } else if constexpr (detail::is_braces_constructible_t<
277 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
278 detail::any_type, detail::any_type, detail::any_type, detail::any_type,
279 detail::any_type>{}) {
280 auto&& [p1, p2, p3, p4, p5, p6, p7, p8, p9] = object;
281 return visitor(p1, p2, p3, p4, p5, p6, p7, p8, p9);
282 } else if constexpr (detail::is_braces_constructible_t<
283 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
284 detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
285 auto&& [p1, p2, p3, p4, p5, p6, p7, p8] = object;
286 return visitor(p1, p2, p3, p4, p5, p6, p7, p8);
287 } else if constexpr (detail::is_braces_constructible_t<
288 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
289 detail::any_type, detail::any_type, detail::any_type>{}) {
290 auto&& [p1, p2, p3, p4, p5, p6, p7] = object;
291 return visitor(p1, p2, p3, p4, p5, p6, p7);
292 } else if constexpr (detail::is_braces_constructible_t<
293 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
294 detail::any_type, detail::any_type>{}) {
295 auto&& [p1, p2, p3, p4, p5, p6] = object;
296 return visitor(p1, p2, p3, p4, p5, p6);
297 } else if constexpr (detail::is_braces_constructible_t<
298 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type,
299 detail::any_type>{}) {
300 auto&& [p1, p2, p3, p4, p5] = object;
301 return visitor(p1, p2, p3, p4, p5);
302 } else if constexpr (detail::is_braces_constructible_t<
303 type, detail::any_type, detail::any_type, detail::any_type, detail::any_type>{}) {
304 auto&& [p1, p2, p3, p4] = object;
305 return visitor(p1, p2, p3, p4);
306 } else if constexpr (detail::is_braces_constructible_t<
307 type, detail::any_type, detail::any_type, detail::any_type>{}) {
308 auto&& [p1, p2, p3] = object;
309 return visitor(p1, p2, p3);
310 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type, detail::any_type>{}) {
311 auto&& [p1, p2] = object;
312 return visitor(p1, p2);
313 } else if constexpr (detail::is_braces_constructible_t<type, detail::any_type>{}) {
314 auto&& [p1] = object;
315 return visitor(p1);
316 }
317
318 GAIA_ASSERT2(false, "Unsupported number of members");
319 }
320
321 GAIA_MSVC_WARNING_POP() // C4702
322 } // namespace meta
323} // namespace gaia
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition reflection.h:25