Flecs v3.2
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
lifecycle_traits.hpp
Go to the documentation of this file.
1
6#pragma once
7
8namespace flecs
9{
10
11namespace _
12{
13
14inline void ecs_ctor_illegal(void *, int32_t, const ecs_type_info_t *ti) {
15 ecs_abort(ECS_INVALID_OPERATION, "invalid constructor for %s", ti->name);
16}
17
18inline void ecs_dtor_illegal(void *, int32_t, const ecs_type_info_t *ti) {
19 ecs_abort(ECS_INVALID_OPERATION, "invalid destructor for %s", ti->name);
20}
21
22inline void ecs_copy_illegal(
23 void *, const void *, int32_t, const ecs_type_info_t *ti)
24{
25 ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name);
26}
27
28inline void ecs_move_illegal(void *, void *, int32_t, const ecs_type_info_t *ti) {
29 ecs_abort(ECS_INVALID_OPERATION, "invalid move assignment for %s", ti->name);
30}
31
32inline void ecs_copy_ctor_illegal(
33 void *, const void *, int32_t, const ecs_type_info_t *ti)
34{
35 ecs_abort(ECS_INVALID_OPERATION, "invalid copy construct for %s", ti->name);
36}
37
38inline void ecs_move_ctor_illegal(
39 void *, void *, int32_t, const ecs_type_info_t *ti)
40{
41 ecs_abort(ECS_INVALID_OPERATION, "invalid move construct for %s", ti->name);
42}
43
44
45// T()
46// Can't coexist with T(flecs::entity) or T(flecs::world, flecs::entity)
47template <typename T>
48void ctor_impl(void *ptr, int32_t count, const ecs_type_info_t *info) {
49 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
50 ECS_INTERNAL_ERROR, NULL);
51 T *arr = static_cast<T*>(ptr);
52 for (int i = 0; i < count; i ++) {
53 FLECS_PLACEMENT_NEW(&arr[i], T);
54 }
55}
56
57// ~T()
58template <typename T>
59void dtor_impl(void *ptr, int32_t count, const ecs_type_info_t *info) {
60 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
61 ECS_INTERNAL_ERROR, NULL);
62 T *arr = static_cast<T*>(ptr);
63 for (int i = 0; i < count; i ++) {
64 arr[i].~T();
65 }
66}
67
68// T& operator=(const T&)
69template <typename T>
70void copy_impl(void *dst_ptr, const void *src_ptr, int32_t count,
71 const ecs_type_info_t *info)
72{
73 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
74 ECS_INTERNAL_ERROR, NULL);
75 T *dst_arr = static_cast<T*>(dst_ptr);
76 const T *src_arr = static_cast<const T*>(src_ptr);
77 for (int i = 0; i < count; i ++) {
78 dst_arr[i] = src_arr[i];
79 }
80}
81
82// T& operator=(T&&)
83template <typename T>
84void move_impl(void *dst_ptr, void *src_ptr, int32_t count,
85 const ecs_type_info_t *info)
86{
87 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
88 ECS_INTERNAL_ERROR, NULL);
89 T *dst_arr = static_cast<T*>(dst_ptr);
90 T *src_arr = static_cast<T*>(src_ptr);
91 for (int i = 0; i < count; i ++) {
92 dst_arr[i] = FLECS_MOV(src_arr[i]);
93 }
94}
95
96// T(T&)
97template <typename T>
98void copy_ctor_impl(void *dst_ptr, const void *src_ptr, int32_t count,
99 const ecs_type_info_t *info)
100{
101 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
102 ECS_INTERNAL_ERROR, NULL);
103 T *dst_arr = static_cast<T*>(dst_ptr);
104 const T *src_arr = static_cast<const T*>(src_ptr);
105 for (int i = 0; i < count; i ++) {
106 FLECS_PLACEMENT_NEW(&dst_arr[i], T(src_arr[i]));
107 }
108}
109
110// T(T&&)
111template <typename T>
112void move_ctor_impl(void *dst_ptr, void *src_ptr, int32_t count,
113 const ecs_type_info_t *info)
114{
115 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
116 ECS_INTERNAL_ERROR, NULL);
117 T *dst_arr = static_cast<T*>(dst_ptr);
118 T *src_arr = static_cast<T*>(src_ptr);
119 for (int i = 0; i < count; i ++) {
120 FLECS_PLACEMENT_NEW(&dst_arr[i], T(FLECS_MOV(src_arr[i])));
121 }
122}
123
124// T(T&&), ~T()
125// Typically used when moving to a new table, and removing from the old table
126template <typename T>
127void ctor_move_dtor_impl(void *dst_ptr, void *src_ptr, int32_t count,
128 const ecs_type_info_t *info)
129{
130 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
131 ECS_INTERNAL_ERROR, NULL);
132 T *dst_arr = static_cast<T*>(dst_ptr);
133 T *src_arr = static_cast<T*>(src_ptr);
134 for (int i = 0; i < count; i ++) {
135 FLECS_PLACEMENT_NEW(&dst_arr[i], T(FLECS_MOV(src_arr[i])));
136 src_arr[i].~T();
137 }
138}
139
140// Move assign + dtor (non-trivial move assignment)
141// Typically used when moving a component to a deleted component
142template <typename T, if_not_t<
143 std::is_trivially_move_assignable<T>::value > = 0>
144void move_dtor_impl(void *dst_ptr, void *src_ptr, int32_t count,
145 const ecs_type_info_t *info)
146{
147 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
148 ECS_INTERNAL_ERROR, NULL);
149 T *dst_arr = static_cast<T*>(dst_ptr);
150 T *src_arr = static_cast<T*>(src_ptr);
151 for (int i = 0; i < count; i ++) {
152 // Move assignment should free dst & assign dst to src
153 dst_arr[i] = FLECS_MOV(src_arr[i]);
154 // Destruct src. Move should have left object in a state where it no
155 // longer holds resources, but it still needs to be destructed.
156 src_arr[i].~T();
157 }
158}
159
160// Move assign + dtor (trivial move assignment)
161// Typically used when moving a component to a deleted component
162template <typename T, if_t<
163 std::is_trivially_move_assignable<T>::value > = 0>
164void move_dtor_impl(void *dst_ptr, void *src_ptr, int32_t count,
165 const ecs_type_info_t *info)
166{
167 (void)info; ecs_assert(info->size == ECS_SIZEOF(T),
168 ECS_INTERNAL_ERROR, NULL);
169 T *dst_arr = static_cast<T*>(dst_ptr);
170 T *src_arr = static_cast<T*>(src_ptr);
171 for (int i = 0; i < count; i ++) {
172 // Cleanup resources of dst
173 dst_arr[i].~T();
174 // Copy src to dst
175 dst_arr[i] = FLECS_MOV(src_arr[i]);
176 // No need to destruct src. Since this is a trivial move the code
177 // should be agnostic to the address of the component which means we
178 // can pretend nothing got destructed.
179 }
180}
181
182} // _
183
184// Trait to test if type is constructible by flecs
185template <typename T>
187 static constexpr bool value =
188 std::is_default_constructible<actual_type_t<T>>::value;
189};
190
191namespace _
192{
193
194// Trivially constructible
195template <typename T, if_t< std::is_trivially_constructible<T>::value > = 0>
196ecs_xtor_t ctor() {
197 return nullptr;
198}
199
200// Not constructible by flecs
201template <typename T, if_t<
202 ! std::is_default_constructible<T>::value > = 0>
203ecs_xtor_t ctor() {
204 return ecs_ctor_illegal;
205}
206
207// Default constructible
208template <typename T, if_t<
209 ! std::is_trivially_constructible<T>::value &&
210 std::is_default_constructible<T>::value > = 0>
211ecs_xtor_t ctor() {
212 return ctor_impl<T>;
213}
214
215// No dtor
216template <typename T, if_t< std::is_trivially_destructible<T>::value > = 0>
217ecs_xtor_t dtor() {
218 return nullptr;
219}
220
221// Dtor
222template <typename T, if_t<
223 std::is_destructible<T>::value &&
224 ! std::is_trivially_destructible<T>::value > = 0>
225ecs_xtor_t dtor() {
226 return dtor_impl<T>;
227}
228
229// Assert when the type cannot be destructed
230template <typename T, if_not_t< std::is_destructible<T>::value > = 0>
231ecs_xtor_t dtor() {
232 flecs_static_assert(always_false<T>::value,
233 "component type must be destructible");
234 return ecs_dtor_illegal;
235}
236
237// Trivially copyable
238template <typename T, if_t< std::is_trivially_copyable<T>::value > = 0>
239ecs_copy_t copy() {
240 return nullptr;
241}
242
243// Not copyable
244template <typename T, if_t<
245 ! std::is_trivially_copyable<T>::value &&
246 ! std::is_copy_assignable<T>::value > = 0>
247ecs_copy_t copy() {
248 return ecs_copy_illegal;
249}
250
251// Copy assignment
252template <typename T, if_t<
253 std::is_copy_assignable<T>::value &&
254 ! std::is_trivially_copyable<T>::value > = 0>
255ecs_copy_t copy() {
256 return copy_impl<T>;
257}
258
259// Trivially move assignable
260template <typename T, if_t< std::is_trivially_move_assignable<T>::value > = 0>
261ecs_move_t move() {
262 return nullptr;
263}
264
265// Component types must be move assignable
266template <typename T, if_not_t< std::is_move_assignable<T>::value > = 0>
267ecs_move_t move() {
268 flecs_static_assert(always_false<T>::value,
269 "component type must be move assignable");
270 return ecs_move_illegal;
271}
272
273// Move assignment
274template <typename T, if_t<
275 std::is_move_assignable<T>::value &&
276 ! std::is_trivially_move_assignable<T>::value > = 0>
277ecs_move_t move() {
278 return move_impl<T>;
279}
280
281// Trivially copy constructible
282template <typename T, if_t<
283 std::is_trivially_copy_constructible<T>::value > = 0>
284ecs_copy_t copy_ctor() {
285 return nullptr;
286}
287
288// No copy ctor
289template <typename T, if_t< ! std::is_copy_constructible<T>::value > = 0>
290ecs_copy_t copy_ctor() {
291 return ecs_copy_ctor_illegal;
292}
293
294// Copy ctor
295template <typename T, if_t<
296 std::is_copy_constructible<T>::value &&
297 ! std::is_trivially_copy_constructible<T>::value > = 0>
298ecs_copy_t copy_ctor() {
299 return copy_ctor_impl<T>;
300}
301
302// Trivially move constructible
303template <typename T, if_t<
304 std::is_trivially_move_constructible<T>::value > = 0>
305ecs_move_t move_ctor() {
306 return nullptr;
307}
308
309// Component types must be move constructible
310template <typename T, if_not_t< std::is_move_constructible<T>::value > = 0>
311ecs_move_t move_ctor() {
312 flecs_static_assert(always_false<T>::value,
313 "component type must be move constructible");
314 return ecs_move_ctor_illegal;
315}
316
317// Move ctor
318template <typename T, if_t<
319 std::is_move_constructible<T>::value &&
320 ! std::is_trivially_move_constructible<T>::value > = 0>
321ecs_move_t move_ctor() {
322 return move_ctor_impl<T>;
323}
324
325// Trivial merge (move assign + dtor)
326template <typename T, if_t<
327 std::is_trivially_move_constructible<T>::value &&
328 std::is_trivially_destructible<T>::value > = 0>
329ecs_move_t ctor_move_dtor() {
330 return nullptr;
331}
332
333// Component types must be move constructible and destructible
334template <typename T, if_t<
335 ! std::is_move_constructible<T>::value ||
336 ! std::is_destructible<T>::value > = 0>
337ecs_move_t ctor_move_dtor() {
338 flecs_static_assert(always_false<T>::value,
339 "component type must be move constructible and destructible");
340 return ecs_move_ctor_illegal;
341}
342
343// Merge ctor + dtor
344template <typename T, if_t<
345 !(std::is_trivially_move_constructible<T>::value &&
346 std::is_trivially_destructible<T>::value) &&
347 std::is_move_constructible<T>::value &&
348 std::is_destructible<T>::value > = 0>
349ecs_move_t ctor_move_dtor() {
350 return ctor_move_dtor_impl<T>;
351}
352
353// Trivial merge (move assign + dtor)
354template <typename T, if_t<
355 std::is_trivially_move_assignable<T>::value &&
356 std::is_trivially_destructible<T>::value > = 0>
357ecs_move_t move_dtor() {
358 return nullptr;
359}
360
361// Component types must be move constructible and destructible
362template <typename T, if_t<
363 ! std::is_move_assignable<T>::value ||
364 ! std::is_destructible<T>::value > = 0>
365ecs_move_t move_dtor() {
366 flecs_static_assert(always_false<T>::value,
367 "component type must be move constructible and destructible");
368 return ecs_move_ctor_illegal;
369}
370
371// Merge assign + dtor
372template <typename T, if_t<
373 !(std::is_trivially_move_assignable<T>::value &&
374 std::is_trivially_destructible<T>::value) &&
375 std::is_move_assignable<T>::value &&
376 std::is_destructible<T>::value > = 0>
377ecs_move_t move_dtor() {
378 return move_dtor_impl<T>;
379}
380
381} // _
382} // flecs
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:351
#define ecs_abort(error_code,...)
Abort.
Definition log.h:342
void(* ecs_copy_t)(void *dst_ptr, const void *src_ptr, int32_t count, const ecs_type_info_t *type_info)
Copy is invoked when a component is copied into another component.
Definition flecs.h:645
void(* ecs_move_t)(void *dst_ptr, void *src_ptr, int32_t count, const ecs_type_info_t *type_info)
Move is invoked when a component is moved to another component.
Definition flecs.h:652
void(* ecs_xtor_t)(void *ptr, int32_t count, const ecs_type_info_t *type_info)
Constructor/destructor callback.
Definition flecs.h:639
Type that contains component information (passed to ctors/dtors/...)
Definition flecs.h:896
ecs_size_t size
Size of type.
Definition flecs.h:897
const char * name
Type name.
Definition flecs.h:901