Flecs: include/flecs/addons/cpp/utils/utils.hpp Source File
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
9
10// Macros so that C++ new calls can allocate using ecs_os_api memory allocation functions
11// Rationale:
12// - Using macros here instead of a templated function bc clients might override ecs_os_malloc
13// to contain extra debug info like source tracking location. Using a template function
14// in that scenario would collapse all source location into said function vs. the
15// actual call site
16// - FLECS_PLACEMENT_NEW(): exists to remove any naked new calls/make it easy to identify any regressions
17// by grepping for new/delete
18
19#define FLECS_PLACEMENT_NEW(_ptr, _type) ::new(flecs::_::placement_new_tag, _ptr) _type
20#define FLECS_NEW(_type) FLECS_PLACEMENT_NEW(ecs_os_malloc(sizeof(_type)), _type)
21#define FLECS_DELETE(_ptr) \
22 do { \
23 if (_ptr) { \
24 flecs::_::destruct_obj(_ptr); \
25 ecs_os_free(_ptr); \
26 } \
27 } while (false)
28
29/* Faster (compile time) alternatives to std::move / std::forward. From:
30 * https://www.foonathan.net/2020/09/move-forward/
31 */
32
33#define FLECS_MOV(...) \
34 static_cast<flecs::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__)
35
36#define FLECS_FWD(...) \
37 static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
38
39namespace flecs
40{
41
42namespace _
43{
44
45// Dummy Placement new tag to disambiguate from any other operator new overrides
46 struct placement_new_tag_t{};
47constexpr placement_new_tag_t placement_new_tag{};
48template<class Ty> inline void destruct_obj(Ty* _ptr) { _ptr->~Ty(); }
49template<class Ty> inline void free_obj(void* _ptr) {
50 if (_ptr) {
51 destruct_obj(static_cast<Ty*>(_ptr));
52 ecs_os_free(_ptr);
53 }
54}
55
56} // namespace _
57
58} // namespace flecs
59
60// Allows overriding flecs_static_assert, which is useful when testing
61#ifndef flecs_static_assert
62#define flecs_static_assert(cond, str) static_assert(cond, str)
63#endif
64
65inline void* operator new(size_t, flecs::_::placement_new_tag_t, void* _ptr) noexcept { return _ptr; }
66inline void operator delete(void*, flecs::_::placement_new_tag_t, void*) noexcept { }
67
68namespace flecs
69{
70
71// faster (compile time) alternative to std::conditional
72 template <bool> struct condition;
73
74 template <> struct condition<false> {
75 template <typename T, typename F> using type = F;
76};
77
78 template <> struct condition<true> {
79 template <typename T, typename F> using type = T;
80};
81
82// C++11/C++14 convenience template replacements
83
84template <bool C, typename T, typename F>
85using conditional_t = typename condition<C>::template type<T, F>;
86
87template <typename T>
88using decay_t = typename std::decay<T>::type;
89
90template <bool V, typename T = void>
91using enable_if_t = typename std::enable_if<V, T>::type;
92
93template <typename T>
94using remove_pointer_t = typename std::remove_pointer<T>::type;
95
96template <typename T>
97using remove_reference_t = typename std::remove_reference<T>::type;
98
99template <typename T>
100using underlying_type_t = typename std::underlying_type<T>::type;
101
102using std::is_base_of;
103using std::is_empty;
104using std::is_const;
105using std::is_pointer;
106using std::is_reference;
107using std::is_volatile;
108using std::is_same;
109using std::is_enum;
110
111// GCC 4.9.2 compatibility: missing C++11 type traits
112#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 9)
113// Direct implementations for missing type traits in GCC 4.9.2
114} // namespace flecs
115
116namespace std {
117 // Only implement the ones that are actually missing in GCC 4.9.2
118 template<typename T>
119 struct is_trivially_constructible {
120 static const bool value = __is_pod(T);
121 };
122
123 template<typename T>
124 struct is_trivially_move_assignable {
125 static const bool value = __is_pod(T);
126 };
127
128 template<typename T>
129 struct is_trivially_copy_assignable {
130 static const bool value = __is_pod(T);
131 };
132
133 template<typename T>
134 struct is_trivially_copy_constructible {
135 static const bool value = __is_pod(T);
136 };
137
138 template<typename T>
139 struct is_trivially_move_constructible {
140 static const bool value = __is_pod(T);
141 };
142
143 template<typename T>
144 struct is_trivially_copyable {
145 static const bool value = __is_pod(T);
146 };
147}
148
149namespace flecs {
150#else
151using std::is_trivially_constructible;
152using std::is_trivially_move_assignable;
153using std::is_trivially_copy_assignable;
154using std::is_trivially_copy_constructible;
155using std::is_trivially_move_constructible;
156using std::is_trivially_copyable;
157#endif
158
159// These exist in GCC 4.9.2, so we can always use them
160using std::is_move_assignable;
161using std::is_move_constructible;
162using std::is_copy_constructible;
163using std::is_trivially_destructible;
164
165// Determine constness even if T is a pointer type
166template <typename T>
167using is_const_p = is_const< remove_pointer_t<T> >;
168
169// Apply cv modifiers from source type to destination type
170// (from: https://stackoverflow.com/questions/52559336/add-const-to-type-if-template-arg-is-const)
171template<class Src, class Dst>
172using transcribe_const_t = conditional_t<is_const<Src>::value, Dst const, Dst>;
173
174template<class Src, class Dst>
175using transcribe_volatile_t = conditional_t<is_volatile<Src>::value, Dst volatile, Dst>;
176
177template<class Src, class Dst>
178using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;
179
180template<class Src, class Dst>
181using transcribe_pointer_t = conditional_t<is_pointer<Src>::value, Dst*, Dst>;
182
183template<class Src, class Dst>
184using transcribe_cvp_t = transcribe_cv_t< Src, transcribe_pointer_t< Src, Dst> >;
185
186
187// More convenience templates. The if_*_t templates use int as default type
188// instead of void. This enables writing code that's a bit less cluttered when
189// the templates are used in a template declaration:
190//
191// enable_if_t<true>* = nullptr
192// vs:
193// if_t<true> = 0
194
195template <bool V>
196using if_t = enable_if_t<V, int>;
197
198template <bool V>
199using if_not_t = enable_if_t<false == V, int>;
200
201namespace _
202{
203
204// Utility to prevent static assert from immediately triggering
205template <class... T>
206 struct always_false {
207 static const bool value = false;
208};
209
210} // namespace _
211
212} // namespace flecs
213
214#include "array.hpp"
215#include "string.hpp"
216#include "enum.hpp"
217#include "stringstream.hpp"
218#include "function_traits.hpp"
array.hpp
Array class.
enum.hpp
Compile time enum reflection utilities.
function_traits.hpp
Compile time utilities to inspect properties of functions.
flecs::_
Int to enum.
Definition component.hpp:18
string.hpp
String utility that doesn't implicitly allocate memory.
stringstream.hpp
Wrapper around ecs_strbuf_t that provides a simple stringstream like API.
flecs::_::always_false
Definition utils.hpp:206
flecs::_::placement_new_tag_t
Definition utils.hpp:46
flecs::condition
Definition utils.hpp:72
flecs::type
Type class.
Definition type.hpp:21