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
10
12template <class T, uint N>
13class [[nodiscard]] StaticArray
14{
15public:
16 using value_type = T;
17
18 using size_type = uint;
19
20 static constexpr uint Capacity = N;
21
23 StaticArray() = default;
24
26 explicit StaticArray(std::initializer_list<T> inList)
27 {
28 JPH_ASSERT(inList.size() <= N);
29 for (const T &v : inList)
30 ::new (reinterpret_cast<T *>(&mElements[mSize++])) T(v);
31 }
32
35 {
36 while (mSize < inRHS.mSize)
37 {
38 ::new (&mElements[mSize]) T(inRHS[mSize]);
39 ++mSize;
40 }
41 }
42
45 {
46 if constexpr (!is_trivially_destructible<T>())
47 for (T *e = reinterpret_cast<T *>(mElements), *end = e + mSize; e < end; ++e)
48 e->~T();
49 }
50
52 void clear()
53 {
54 if constexpr (!is_trivially_destructible<T>())
55 for (T *e = reinterpret_cast<T *>(mElements), *end = e + mSize; e < end; ++e)
56 e->~T();
57 mSize = 0;
58 }
59
61 void push_back(const T &inElement)
62 {
63 JPH_ASSERT(mSize < N);
64 ::new (&mElements[mSize++]) T(inElement);
65 }
66
68 template <class... A>
69 void emplace_back(A &&... inElement)
70 {
71 JPH_ASSERT(mSize < N);
72 ::new (&mElements[mSize++]) T(std::forward<A>(inElement)...);
73 }
74
76 void pop_back()
77 {
78 JPH_ASSERT(mSize > 0);
79 reinterpret_cast<T &>(mElements[--mSize]).~T();
80 }
81
83 bool empty() const
84 {
85 return mSize == 0;
86 }
87
90 {
91 return mSize;
92 }
93
96 {
97 return N;
98 }
99
101 void resize(size_type inNewSize)
102 {
103 JPH_ASSERT(inNewSize <= N);
104 if constexpr (!is_trivially_constructible<T>())
105 for (T *element = reinterpret_cast<T *>(mElements) + mSize, *element_end = reinterpret_cast<T *>(mElements) + inNewSize; element < element_end; ++element)
106 ::new (element) T;
107 if constexpr (!is_trivially_destructible<T>())
108 for (T *element = reinterpret_cast<T *>(mElements) + inNewSize, *element_end = reinterpret_cast<T *>(mElements) + mSize; element < element_end; ++element)
109 element->~T();
110 mSize = inNewSize;
111 }
112
113 using const_iterator = const T *;
114
117 {
118 return reinterpret_cast<const T *>(mElements);
119 }
120
122 {
123 return reinterpret_cast<const T *>(mElements + mSize);
124 }
125
126 using iterator = T *;
127
129 {
130 return reinterpret_cast<T *>(mElements);
131 }
132
134 {
135 return reinterpret_cast<T *>(mElements + mSize);
136 }
137
138 const T * data() const
139 {
140 return reinterpret_cast<const T *>(mElements);
141 }
142
143 T * data()
144 {
145 return reinterpret_cast<T *>(mElements);
146 }
147
149 T & operator [] (size_type inIdx)
150 {
151 JPH_ASSERT(inIdx < mSize);
152 return reinterpret_cast<T &>(mElements[inIdx]);
153 }
154
155 const T & operator [] (size_type inIdx) const
156 {
157 JPH_ASSERT(inIdx < mSize);
158 return reinterpret_cast<const T &>(mElements[inIdx]);
159 }
160
162 T & at(size_type inIdx)
163 {
164 JPH_ASSERT(inIdx < mSize);
165 return reinterpret_cast<T &>(mElements[inIdx]);
166 }
167
168 const T & at(size_type inIdx) const
169 {
170 JPH_ASSERT(inIdx < mSize);
171 return reinterpret_cast<const T &>(mElements[inIdx]);
172 }
173
175 const T & front() const
176 {
177 JPH_ASSERT(mSize > 0);
178 return reinterpret_cast<const T &>(mElements[0]);
179 }
180
181 T & front()
182 {
183 JPH_ASSERT(mSize > 0);
184 return reinterpret_cast<T &>(mElements[0]);
185 }
186
188 const T & back() const
189 {
190 JPH_ASSERT(mSize > 0);
191 return reinterpret_cast<const T &>(mElements[mSize - 1]);
192 }
193
194 T & back()
195 {
196 JPH_ASSERT(mSize > 0);
197 return reinterpret_cast<T &>(mElements[mSize - 1]);
198 }
199
202 {
203 size_type p = size_type(inIter - begin());
204 JPH_ASSERT(p < mSize);
205 reinterpret_cast<T &>(mElements[p]).~T();
206 if (p + 1 < mSize)
207 memmove(mElements + p, mElements + p + 1, (mSize - p - 1) * sizeof(T));
208 --mSize;
209 }
210
213 {
214 size_type p = size_type(inBegin - begin());
215 size_type n = size_type(inEnd - inBegin);
216 JPH_ASSERT(inEnd <= end());
217 for (size_type i = 0; i < n; ++i)
218 reinterpret_cast<T &>(mElements[p + i]).~T();
219 if (p + n < mSize)
220 memmove(mElements + p, mElements + p + n, (mSize - p - n) * sizeof(T));
221 mSize -= n;
222 }
223
225 StaticArray<T, N> & operator = (const StaticArray<T, N> &inRHS)
226 {
227 size_type rhs_size = inRHS.size();
228
229 if (static_cast<const void *>(this) != static_cast<const void *>(&inRHS))
230 {
231 clear();
232
233 while (mSize < rhs_size)
234 {
235 ::new (&mElements[mSize]) T(inRHS[mSize]);
236 ++mSize;
237 }
238 }
239
240 return *this;
241 }
242
244 template <uint M>
245 StaticArray<T, N> & operator = (const StaticArray<T, M> &inRHS)
246 {
247 size_type rhs_size = inRHS.size();
248 JPH_ASSERT(rhs_size <= N);
249
250 if (static_cast<const void *>(this) != static_cast<const void *>(&inRHS))
251 {
252 clear();
253
254 while (mSize < rhs_size)
255 {
256 ::new (&mElements[mSize]) T(inRHS[mSize]);
257 ++mSize;
258 }
259 }
260
261 return *this;
262 }
263
265 bool operator == (const StaticArray<T, N> &inRHS) const
266 {
267 if (mSize != inRHS.mSize)
268 return false;
269 for (size_type i = 0; i < mSize; ++i)
270 if (!(reinterpret_cast<const T &>(mElements[i]) == reinterpret_cast<const T &>(inRHS.mElements[i])))
271 return false;
272 return true;
273 }
274
275 bool operator != (const StaticArray<T, N> &inRHS) const
276 {
277 if (mSize != inRHS.mSize)
278 return true;
279 for (size_type i = 0; i < mSize; ++i)
280 if (reinterpret_cast<const T &>(mElements[i]) != reinterpret_cast<const T &>(inRHS.mElements[i]))
281 return true;
282 return false;
283 }
284
287 {
288 // Hash length first
289 uint64 ret = Hash<uint32> { } (uint32(size()));
290
291 // Then hash elements
292 for (const T *element = reinterpret_cast<const T *>(mElements), *element_end = reinterpret_cast<const T *>(mElements) + mSize; element < element_end; ++element)
293 HashCombine(ret, *element);
294
295 return ret;
296 }
297
298protected:
299 struct alignas(T) Storage
300 {
301 uint8 mData[sizeof(T)];
302 };
303
304 static_assert(sizeof(T) == sizeof(Storage), "Mismatch in size");
305 static_assert(alignof(T) == alignof(Storage), "Mismatch in alignment");
306
307 size_type mSize = 0;
308 Storage mElements[N];
309};
310
312
313JPH_SUPPRESS_WARNING_PUSH
314JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
315
316namespace std
317{
319 template <class T, JPH::uint N>
320 struct hash<JPH::StaticArray<T, N>>
321 {
322 size_t operator () (const JPH::StaticArray<T, N> &inRHS) const
323 {
324 return std::size_t(inRHS.GetHash());
325 }
326 };
327}
328
329JPH_SUPPRESS_WARNING_POP
std::uint8_t uint8
Definition Core.h:454
std::uint64_t uint64
Definition Core.h:457
unsigned int uint
Definition Core.h:453
#define JPH_NAMESPACE_END
Definition Core.h:379
#define JPH_CLANG_SUPPRESS_WARNING(w)
Definition Core.h:263
std::uint32_t uint32
Definition Core.h:456
#define JPH_NAMESPACE_BEGIN
Definition Core.h:373
void HashCombine(uint64 &ioSeed, const T &inValue)
Commonly used types.
Definition HashCombine.h:148
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
Simple variable length array backed by a fixed size buffer.
Definition StaticArray.h:14
StaticArray()=default
Default constructor.
void push_back(const T &inElement)
Add element to the back of the array.
Definition StaticArray.h:61
size_type capacity() const
Returns maximum amount of elements the array can hold.
Definition StaticArray.h:95
iterator end()
Definition StaticArray.h:133
T * data()
Definition StaticArray.h:143
void clear()
Destruct all elements and set length to zero.
Definition StaticArray.h:52
T value_type
Definition StaticArray.h:16
iterator begin()
Definition StaticArray.h:128
StaticArray(std::initializer_list< T > inList)
Constructor from initializer list.
Definition StaticArray.h:26
const T * const_iterator
Definition StaticArray.h:113
T * iterator
Definition StaticArray.h:126
T & front()
Definition StaticArray.h:181
void erase(const_iterator inIter)
Remove one element from the array.
Definition StaticArray.h:201
const_iterator begin() const
Iterators.
Definition StaticArray.h:116
uint size_type
Definition StaticArray.h:18
const T & back() const
Last element in the array.
Definition StaticArray.h:188
const T * data() const
Definition StaticArray.h:138
void emplace_back(A &&... inElement)
Construct element at the back of the array.
Definition StaticArray.h:69
void erase(const_iterator inBegin, const_iterator inEnd)
Remove multiple element from the array.
Definition StaticArray.h:212
T & at(size_type inIdx)
Access element.
Definition StaticArray.h:162
Storage mElements[N]
Definition StaticArray.h:308
uint64 GetHash() const
Get hash for this array.
Definition StaticArray.h:286
bool empty() const
Returns true if there are no elements in the array.
Definition StaticArray.h:83
StaticArray(const StaticArray< T, N > &inRHS)
Copy constructor.
Definition StaticArray.h:34
const T & front() const
First element in the array.
Definition StaticArray.h:175
T & back()
Definition StaticArray.h:194
const_iterator end() const
Definition StaticArray.h:121
size_type mSize
Definition StaticArray.h:307
size_type size() const
Returns amount of elements in the array.
Definition StaticArray.h:89
void pop_back()
Remove element from the back of the array.
Definition StaticArray.h:76
void resize(size_type inNewSize)
Resize array to new length.
Definition StaticArray.h:101
const T & at(size_type inIdx) const
Definition StaticArray.h:168
~StaticArray()
Destruct all elements.
Definition StaticArray.h:44
Definition Array.h:590
Fallback hash function that calls T::GetHash()
Definition HashCombine.h:59
Definition StaticArray.h:300