Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
StaticArray.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
10template <class T, uint N>
11class [[nodiscard]] StaticArray
12{
13public:
14 using value_type = T;
15
16 using size_type = uint;
17
18 static constexpr uint Capacity = N;
19
21 StaticArray() = default;
22
24 explicit StaticArray(std::initializer_list<T> inList)
25 {
26 JPH_ASSERT(inList.size() <= N);
27 for (typename std::initializer_list<T>::iterator i = inList.begin(); i != inList.end(); ++i)
28 ::new (reinterpret_cast<T *>(&mElements[mSize++])) T(*i);
29 }
30
33 {
34 while (mSize < inRHS.mSize)
35 {
36 ::new (&mElements[mSize]) T(inRHS[mSize]);
37 ++mSize;
38 }
39 }
40
43 {
44 if constexpr (!is_trivially_destructible<T>())
45 for (T *e = reinterpret_cast<T *>(mElements), *end = e + mSize; e < end; ++e)
46 e->~T();
47 }
48
50 void clear()
51 {
52 if constexpr (!is_trivially_destructible<T>())
53 for (T *e = reinterpret_cast<T *>(mElements), *end = e + mSize; e < end; ++e)
54 e->~T();
55 mSize = 0;
56 }
57
59 void push_back(const T &inElement)
60 {
61 JPH_ASSERT(mSize < N);
62 ::new (&mElements[mSize++]) T(inElement);
63 }
64
66 template <class... A>
67 void emplace_back(A &&... inElement)
68 {
69 JPH_ASSERT(mSize < N);
70 ::new (&mElements[mSize++]) T(std::forward<A>(inElement)...);
71 }
72
74 void pop_back()
75 {
76 JPH_ASSERT(mSize > 0);
77 reinterpret_cast<T &>(mElements[--mSize]).~T();
78 }
79
81 bool empty() const
82 {
83 return mSize == 0;
84 }
85
88 {
89 return mSize;
90 }
91
94 {
95 return N;
96 }
97
99 void resize(size_type inNewSize)
100 {
101 JPH_ASSERT(inNewSize <= N);
102 if constexpr (!is_trivially_constructible<T>())
103 for (T *element = reinterpret_cast<T *>(mElements) + mSize, *element_end = reinterpret_cast<T *>(mElements) + inNewSize; element < element_end; ++element)
104 ::new (element) T;
105 if constexpr (!is_trivially_destructible<T>())
106 for (T *element = reinterpret_cast<T *>(mElements) + inNewSize, *element_end = reinterpret_cast<T *>(mElements) + mSize; element < element_end; ++element)
107 element->~T();
108 mSize = inNewSize;
109 }
110
111 using const_iterator = const T *;
112
115 {
116 return reinterpret_cast<const T *>(mElements);
117 }
118
120 {
121 return reinterpret_cast<const T *>(mElements + mSize);
122 }
123
124 using iterator = T *;
125
127 {
128 return reinterpret_cast<T *>(mElements);
129 }
130
132 {
133 return reinterpret_cast<T *>(mElements + mSize);
134 }
135
136 const T * data() const
137 {
138 return reinterpret_cast<const T *>(mElements);
139 }
140
141 T * data()
142 {
143 return reinterpret_cast<T *>(mElements);
144 }
145
147 T & operator [] (size_type inIdx)
148 {
149 JPH_ASSERT(inIdx < mSize);
150 return reinterpret_cast<T &>(mElements[inIdx]);
151 }
152
153 const T & operator [] (size_type inIdx) const
154 {
155 JPH_ASSERT(inIdx < mSize);
156 return reinterpret_cast<const T &>(mElements[inIdx]);
157 }
158
160 T & at(size_type inIdx)
161 {
162 JPH_ASSERT(inIdx < mSize);
163 return reinterpret_cast<T &>(mElements[inIdx]);
164 }
165
166 const T & at(size_type inIdx) const
167 {
168 JPH_ASSERT(inIdx < mSize);
169 return reinterpret_cast<const T &>(mElements[inIdx]);
170 }
171
173 const T & front() const
174 {
175 JPH_ASSERT(mSize > 0);
176 return reinterpret_cast<const T &>(mElements[0]);
177 }
178
179 T & front()
180 {
181 JPH_ASSERT(mSize > 0);
182 return reinterpret_cast<T &>(mElements[0]);
183 }
184
186 const T & back() const
187 {
188 JPH_ASSERT(mSize > 0);
189 return reinterpret_cast<const T &>(mElements[mSize - 1]);
190 }
191
192 T & back()
193 {
194 JPH_ASSERT(mSize > 0);
195 return reinterpret_cast<T &>(mElements[mSize - 1]);
196 }
197
200 {
201 size_type p = size_type(inIter - begin());
202 JPH_ASSERT(p < mSize);
203 reinterpret_cast<T &>(mElements[p]).~T();
204 if (p + 1 < mSize)
205 memmove(mElements + p, mElements + p + 1, (mSize - p - 1) * sizeof(T));
206 --mSize;
207 }
208
211 {
212 size_type p = size_type(inBegin - begin());
213 size_type n = size_type(inEnd - inBegin);
214 JPH_ASSERT(inEnd <= end());
215 for (size_type i = 0; i < n; ++i)
216 reinterpret_cast<T &>(mElements[p + i]).~T();
217 if (p + n < mSize)
218 memmove(mElements + p, mElements + p + n, (mSize - p - n) * sizeof(T));
219 mSize -= n;
220 }
221
223 StaticArray<T, N> & operator = (const StaticArray<T, N> &inRHS)
224 {
225 size_type rhs_size = inRHS.size();
226
227 if (static_cast<const void *>(this) != static_cast<const void *>(&inRHS))
228 {
229 clear();
230
231 while (mSize < rhs_size)
232 {
233 ::new (&mElements[mSize]) T(inRHS[mSize]);
234 ++mSize;
235 }
236 }
237
238 return *this;
239 }
240
242 template <uint M>
243 StaticArray<T, N> & operator = (const StaticArray<T, M> &inRHS)
244 {
245 size_type rhs_size = inRHS.size();
246 JPH_ASSERT(rhs_size <= N);
247
248 if (static_cast<const void *>(this) != static_cast<const void *>(&inRHS))
249 {
250 clear();
251
252 while (mSize < rhs_size)
253 {
254 ::new (&mElements[mSize]) T(inRHS[mSize]);
255 ++mSize;
256 }
257 }
258
259 return *this;
260 }
261
263 bool operator == (const StaticArray<T, N> &inRHS) const
264 {
265 if (mSize != inRHS.mSize)
266 return false;
267 for (size_type i = 0; i < mSize; ++i)
268 if (!(reinterpret_cast<const T &>(mElements[i]) == reinterpret_cast<const T &>(inRHS.mElements[i])))
269 return false;
270 return true;
271 }
272
273 bool operator != (const StaticArray<T, N> &inRHS) const
274 {
275 if (mSize != inRHS.mSize)
276 return true;
277 for (size_type i = 0; i < mSize; ++i)
278 if (reinterpret_cast<const T &>(mElements[i]) != reinterpret_cast<const T &>(inRHS.mElements[i]))
279 return true;
280 return false;
281 }
282
283protected:
284 struct alignas(T) Storage
285 {
286 uint8 mData[sizeof(T)];
287 };
288
289 static_assert(sizeof(T) == sizeof(Storage), "Mismatch in size");
290 static_assert(alignof(T) == alignof(Storage), "Mismatch in alignment");
291
292 size_type mSize = 0;
293 Storage mElements[N];
294};
295
297
298JPH_SUPPRESS_WARNING_PUSH
299JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
300
301namespace std
302{
304 template <class T, JPH::uint N>
305 struct hash<JPH::StaticArray<T, N>>
306 {
307 size_t operator () (const JPH::StaticArray<T, N> &inRHS) const
308 {
309 std::size_t ret = 0;
310
311 // Hash length first
312 JPH::HashCombine(ret, inRHS.size());
313
314 // Then hash elements
315 for (const T &t : inRHS)
316 JPH::HashCombine(ret, t);
317
318 return ret;
319 }
320 };
321}
322
323JPH_SUPPRESS_WARNING_POP
std::uint8_t uint8
Definition: Core.h:427
unsigned int uint
Definition: Core.h:426
#define JPH_NAMESPACE_END
Definition: Core.h:354
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition: Core.h:241
#define JPH_NAMESPACE_BEGIN
Definition: Core.h:348
#define JPH_ASSERT(...)
Definition: IssueReporting.h:33
Simple variable length array backed by a fixed size buffer.
Definition: StaticArray.h:12
StaticArray()=default
Default constructor.
void push_back(const T &inElement)
Add element to the back of the array.
Definition: StaticArray.h:59
size_type capacity() const
Returns maximum amount of elements the array can hold.
Definition: StaticArray.h:93
iterator end()
Definition: StaticArray.h:131
T * data()
Definition: StaticArray.h:141
void clear()
Destruct all elements and set length to zero.
Definition: StaticArray.h:50
T value_type
Definition: StaticArray.h:14
iterator begin()
Definition: StaticArray.h:126
StaticArray(std::initializer_list< T > inList)
Constructor from initializer list.
Definition: StaticArray.h:24
const T * const_iterator
Definition: StaticArray.h:111
T * iterator
Definition: StaticArray.h:124
T & front()
Definition: StaticArray.h:179
void erase(const_iterator inIter)
Remove one element from the array.
Definition: StaticArray.h:199
const_iterator begin() const
Iterators.
Definition: StaticArray.h:114
uint size_type
Definition: StaticArray.h:16
const T & back() const
Last element in the array.
Definition: StaticArray.h:186
const T * data() const
Definition: StaticArray.h:136
void emplace_back(A &&... inElement)
Construct element at the back of the array.
Definition: StaticArray.h:67
void erase(const_iterator inBegin, const_iterator inEnd)
Remove multiple element from the array.
Definition: StaticArray.h:210
T & at(size_type inIdx)
Access element.
Definition: StaticArray.h:160
Storage mElements[N]
Definition: StaticArray.h:293
bool empty() const
Returns true if there are no elements in the array.
Definition: StaticArray.h:81
StaticArray(const StaticArray< T, N > &inRHS)
Copy constructor.
Definition: StaticArray.h:32
const T & front() const
First element in the array.
Definition: StaticArray.h:173
T & back()
Definition: StaticArray.h:192
const_iterator end() const
Definition: StaticArray.h:119
size_type mSize
Definition: StaticArray.h:292
size_type size() const
Returns amount of elements in the array.
Definition: StaticArray.h:87
void pop_back()
Remove element from the back of the array.
Definition: StaticArray.h:74
void resize(size_type inNewSize)
Resize array to new length.
Definition: StaticArray.h:99
const T & at(size_type inIdx) const
Definition: StaticArray.h:166
~StaticArray()
Destruct all elements.
Definition: StaticArray.h:42
Definition: Reference.h:204
Definition: StaticArray.h:285