nCine 2025.06.r503-ff15d8d
A cross-platform 2D game engine
Loading...
Searching...
No Matches
utility.h
1#ifndef NCTL_UTILITY
2#define NCTL_UTILITY
3
4#include <cstring> // for `memcpy()`
5#include "type_traits.h"
6
7namespace nctl {
8
10template <class T>
11inline typename removeReference<T>::type &&move(T &&arg)
12{
13 return static_cast<typename removeReference<T>::type &&>(arg);
14}
15
16namespace detail {
17
19 template <bool value>
21 {
22 template <class T>
23 inline static void constructObject(T *ptr)
24 {
25 new (ptr) T();
26 }
27
28 template <class T>
29 inline static void constructArray(T *ptr, unsigned int numElements)
30 {
31 for (unsigned int i = 0; i < numElements; i++)
32 new (ptr + i) T();
33 }
34
35 template <class T>
36 inline static void copyConstructObject(T *dest, const T *src)
37 {
38 new (dest) T(*src);
39 }
40
41 template <class T>
42 inline static void copyConstructArray(T *dest, const T *src, unsigned int numElements)
43 {
44 for (unsigned int i = 0; i < numElements; i++)
45 new (dest + i) T(src[i]);
46 }
47
48 template <class T>
49 inline static void moveConstructObject(T *dest, T *src)
50 {
51 new (dest) T(nctl::move(*src));
52 }
53
54 template <class T>
55 inline static void moveConstructArray(T *dest, T *src, unsigned int numElements)
56 {
57 for (unsigned int i = 0; i < numElements; i++)
58 new (dest + i) T(nctl::move(src[i]));
59 }
60 };
61
63 template <>
65 {
66 template <class T>
67 inline static void constructObject(T *ptr)
68 {
69 }
70
71 template <class T>
72 inline static void constructArray(T *ptr, unsigned int numElements)
73 {
74 }
75
76 template <class T>
77 inline static void copyConstructObject(T *dest, const T *src)
78 {
79 memcpy(dest, src, sizeof(T));
80 }
81
82 template <class T>
83 inline static void copyConstructArray(T *dest, const T *src, unsigned int numElements)
84 {
85 memcpy(dest, src, numElements * sizeof(T));
86 }
87
88 template <class T>
89 inline static void moveConstructObject(T *dest, T *src)
90 {
91 memcpy(dest, src, sizeof(T));
92 }
93
94 template <class T>
95 inline static void moveConstructArray(T *dest, T *src, unsigned int numElements)
96 {
97 memcpy(dest, src, numElements * sizeof(T));
98 }
99 };
100
102 template <bool value>
104 {
105 template <class T>
106 inline static void destructObject(T *ptr)
107 {
108 ptr->~T();
109 }
110
111 template <class T>
112 inline static void destructArray(T *ptr, unsigned int numElements)
113 {
114 for (unsigned int i = 0; i < numElements; i++)
115 ptr[numElements - i - 1].~T();
116 }
117 };
118
120 template <>
122 {
123 template <class T>
124 inline static void destructObject(T *ptr)
125 {
126 }
127
128 template <class T>
129 inline static void destructArray(T *ptr, unsigned int numElements)
130 {
131 }
132 };
133
135 template <bool value>
137 {
138 template <class T>
139 inline static void copyAssignObject(T *dest, const T *src)
140 {
141 *dest = *src;
142 }
143
144 template <class T>
145 inline static void copyAssignArray(T *dest, const T *src, unsigned int numElements)
146 {
147 for (unsigned int i = 0; i < numElements; i++)
148 dest[i] = src[i];
149 }
150
151 template <class T>
152 inline static void moveAssignObject(T *dest, T *src)
153 {
154 *dest = nctl::move(*src);
155 }
156
157 template <class T>
158 inline static void moveAssignArray(T *dest, T *src, unsigned int numElements)
159 {
160 for (unsigned int i = 0; i < numElements; i++)
161 dest[i] = nctl::move(src[i]);
162 }
163 };
164
166 template <>
168 {
169 template <class T>
170 inline static void copyAssignObject(T *dest, const T *src)
171 {
172 memcpy(dest, src, sizeof(T));
173 }
174
175 template <class T>
176 inline static void copyAssignArray(T *dest, const T *src, unsigned int numElements)
177 {
178 memcpy(dest, src, numElements * sizeof(T));
179 }
180
181 template <class T>
182 inline static void moveAssignObject(T *dest, T *src)
183 {
184 memcpy(dest, src, sizeof(T));
185 }
186
187 template <class T>
188 inline static void moveAssignArray(T *dest, T *src, unsigned int numElements)
189 {
190 memcpy(dest, src, numElements * sizeof(T));
191 }
192 };
193
194}
195
197template <typename T>
198inline constexpr T &&forward(typename removeReference<T>::type &arg)
199{
200 return static_cast<T &&>(arg);
201}
202
203template <typename T>
204inline constexpr T &&forward(typename removeReference<T>::type &&arg)
205{
206 static_assert(!isLValueReference<T>::value, "Invalid lvalue to rvalue conversion");
207 return static_cast<T &&>(arg);
208}
209
211template <class T>
212inline void swap(T &a, T &b)
213{
214 T temp = nctl::move(a);
215 a = nctl::move(b);
216 b = nctl::move(temp);
217}
218
220template <class T>
221inline bool equalTo(const T &a, const T &b)
222{
223 return (a == b);
224}
225
227template <class T>
228inline bool equalTo(const T *a, const T *b)
229{
230 return (a == b);
231}
232
233template <>
234inline bool equalTo<char>(const char *a, const char *b)
235{
236 // `strcmp()` reimplementation to avoid additional dependencies
237 while (*a && (*a == *b))
238 {
239 a++;
240 b++;
241 }
242 const unsigned char result = *reinterpret_cast<const unsigned char *>(a) -
243 *reinterpret_cast<const unsigned char *>(b);
244
245 return (result == 0);
246}
247
248template <class T>
249void constructObject(T *ptr)
250{
251 detail::constructHelpers<isTriviallyConstructible<T>::value>::constructObject(ptr);
252}
253
254template <class T>
255void constructArray(T *ptr, unsigned int numElements)
256{
257 detail::constructHelpers<isTriviallyConstructible<T>::value>::constructArray(ptr, numElements);
258}
259
260template <class T>
261void copyConstructObject(T *dest, const T *src)
262{
263 detail::constructHelpers<isTriviallyConstructible<T>::value>::copyConstructObject(dest, src);
264}
265
266template <class T>
267void copyConstructArray(T *dest, const T *src, unsigned int numElements)
268{
269 detail::constructHelpers<isTriviallyConstructible<T>::value>::copyConstructArray(dest, src, numElements);
270}
271
272template <class T>
273void moveConstructObject(T *dest, T *src)
274{
275 detail::constructHelpers<isTriviallyConstructible<T>::value>::moveConstructObject(dest, src);
276}
277
278template <class T>
279void moveConstructArray(T *dest, T *src, unsigned int numElements)
280{
281 detail::constructHelpers<isTriviallyConstructible<T>::value>::moveConstructArray(dest, src, numElements);
282}
283
284template <class T>
285void destructObject(T *ptr)
286{
287 detail::destructHelpers<isTriviallyDestructible<T>::value>::destructObject(ptr);
288}
289
290template <class T>
291void destructArray(T *ptr, unsigned int numElements)
292{
293 detail::destructHelpers<isTriviallyDestructible<T>::value>::destructArray(ptr, numElements);
294}
295
296template <class T>
297void copyAssignObject(T *dest, const T *src)
298{
299 detail::copyHelpers<isTriviallyCopyable<T>::value>::copyAssignObject(dest, src);
300}
301
302template <class T>
303void copyAssignArray(T *dest, const T *src, unsigned int numElements)
304{
305 detail::copyHelpers<isTriviallyCopyable<T>::value>::copyAssignArray(dest, src, numElements);
306}
307
308template <class T>
309void moveAssignObject(T *dest, T *src)
310{
311 detail::copyHelpers<isTriviallyCopyable<T>::value>::moveAssignObject(dest, src);
312}
313
314template <class T>
315void moveAssignArray(T *dest, T *src, unsigned int numElements)
316{
317 detail::copyHelpers<isTriviallyCopyable<T>::value>::moveAssignArray(dest, src, numElements);
318}
319
320}
321
322#endif
A unique pointer implementation.
Definition UniquePtr.h:118
A container for functions to construct objects and arrays of objects.
Definition utility.h:21
A container for functions to assign objects and arrays of objects.
Definition utility.h:137
A container for functions to destruct objects and arrays of objects.
Definition utility.h:104