CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
StaticVector.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Vector.hpp"
11
13
16
17#include <cstddef>
18#include <iterator>
19#include <memory>
20#include <type_traits>
21
22#define CE_STATIC_VECTOR_ERROR_HANDLING_NONE 0
23#define CE_STATIC_VECTOR_ERROR_HANDLING_THROW 1
24#define CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT 2
25#define CE_STATIC_VECTOR_ERROR_HANDLING_RESCUE 3
26#define CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT_AND_THROW 4
27#define CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT_AND_RESCUE 5
28
29#if !defined(CE_STATIC_VECTOR_ERROR_HANDLING)
30#define CE_STATIC_VECTOR_ERROR_HANDLING CE_STATIC_VECTOR_ERROR_HANDLING_THROW
31#endif
32
33#if CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_NONE
34#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return)
35#elif CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_THROW
36#include <stdexcept>
37#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return) \
38 if(cond) \
39 throw std::out_of_range("itlib::StaticVector out of range")
40#elif CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT
41#include <cassert>
42#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return) assert(!(cond) && "itlib::StaticVector out of range")
43#elif CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_RESCUE
44#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return) \
45 if(cond) \
46 return rescue_return
47#elif CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT_AND_THROW
48#include <cassert>
49#include <stdexcept>
50#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return) \
51 do { \
52 if(cond) { \
53 assert(false && "itlib::StaticVector out of range"); \
54 throw std::out_of_range("itlib::StaticVector out of range"); \
55 } \
56 } while(false)
57#elif CE_STATIC_VECTOR_ERROR_HANDLING == CE_STATIC_VECTOR_ERROR_HANDLING_ASSERT_AND_RESCUE
58#include <cassert>
59#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return) \
60 do { \
61 if(cond) { \
62 assert(false && "itlib::StaticVector out of range"); \
63 return rescue_return; \
64 } \
65 } while(false)
66#else
67#error "Unknown CE_STATIC_VECTOR_ERRROR_HANDLING"
68#endif
69
70#if defined(CE_STATIC_VECTOR_NO_DEBUG_BOUNDS_CHECK)
71#define CE_STATIC_VECTOR_BOUNDS_CHECK(i)
72#else
73#include <cassert>
74#define CE_STATIC_VECTOR_BOUNDS_CHECK(i) assert((i) < this->size())
75#endif
76
77namespace CeresEngine {
78
84 template<typename T, size_t Capacity> struct StaticVector {
86 using value_type = T;
87 using pointer = T*;
88 using const_pointer = const T*;
89 };
90
91 public:
92 using value_type = T;
95 using reference = T&;
96 using const_reference = const T&;
97 using pointer = T*;
98 using const_pointer = const T*;
99 using iterator = T*;
100 using const_iterator = const T*;
101 using reverse_iterator = std::reverse_iterator<iterator>;
102 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
104
105 StaticVector() = default;
106
107 explicit StaticVector(const size_t count) { resize(count); }
108
109 StaticVector(const size_t count, const T& value) {
111
112 for(size_t i = 0; i < count; ++i) {
113 push_back(value);
114 }
115 }
116
117 StaticVector(std::initializer_list<T> l) {
119
120 for(auto&& i : l) {
121 push_back(i);
122 }
123 }
124
126 for(const auto& i : v) {
127 push_back(i);
128 }
129 }
130
131 template<size_t CapacityB> StaticVector(const StaticVector<T, CapacityB>& v) {
133
134 for(const auto& i : v) {
135 push_back(i);
136 }
137 }
138
139 StaticVector(StaticVector&& v) noexcept(std::is_nothrow_move_constructible<T>::value) {
140 for(auto i = v.begin(); i != v.end(); ++i) {
141 emplace_back(std::move(*i));
142 }
143 v.clear();
144 }
145
147
149 if(this == &v) {
150 // prevent self usurp
151 return *this;
152 }
153
154 clear();
155 for(auto& elem : v) {
157 }
158
159 return *this;
160 }
161
162 StaticVector& operator=(StaticVector&& v) noexcept(std::is_nothrow_move_assignable<T>::value) {
163 clear();
164 for(auto i = v.begin(); i != v.end(); ++i) {
165 emplace_back(std::move(*i));
166 }
167
168 v.clear();
169 return *this;
170 }
171
174 return *reinterpret_cast<const T*>(m_data + i);
175 }
176
179 return *reinterpret_cast<T*>(m_data + i);
180 }
181
182 [[nodiscard]] const_reference operator[](const size_type i) const { return at(i); }
183 [[nodiscard]] reference operator[](const size_type i) { return at(i); }
184
185 [[nodiscard]] const_reference front() const { return at(0); }
186 [[nodiscard]] reference front() { return at(0); }
187
188 [[nodiscard]] const_reference back() const { return at(m_size - 1); }
189 [[nodiscard]] reference back() { return at(m_size - 1); }
190
191 [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<const T*>(m_data); }
192 [[nodiscard]] pointer data() noexcept { return reinterpret_cast<T*>(m_data); }
193
194 // iterators
198 [[nodiscard]] iterator end() noexcept { return data() + m_size; }
207
208 // capacity
209 [[nodiscard]] bool empty() const noexcept { return m_size == 0; }
210 [[nodiscard]] size_t size() const noexcept { return m_size; }
211 [[nodiscard]] size_t max_size() const noexcept { return Capacity; }
212 [[nodiscard]] size_t capacity() const noexcept { return Capacity; }
213
214 // modifiers
215 void pop_back() {
216 reinterpret_cast<const T*>(m_data + m_size - 1)->~T();
217 --m_size;
218 }
219
221 while(!empty()) {
222 pop_back();
223 }
224 }
225
232
233 void push_back(T&& v) {
235
236 ::new(m_data + m_size) T(std::move(v));
237 ++m_size;
238 }
239
240 template<typename... Args> void emplace_back(Args&&... args) {
242
243 ::new(m_data + m_size) T(std::forward<Args>(args)...);
244 ++m_size;
245 }
246
249
250 if(position == end()) {
252 return position;
253 }
254
255 emplace_back(std::move(back()));
256
257 for(auto i = end() - 2; i != position; --i) {
258 *i = std::move(*(i - 1));
259 }
260
261 *position = val;
262
263 return position;
264 }
265
266 template<typename... Args> iterator emplace(iterator position, Args&&... args) {
268
269 if(position == end()) {
270 emplace_back(std::forward<Args>(args)...);
271 return position;
272 }
273
274 emplace_back(std::move(back()));
275
276 for(auto i = end() - 2; i != position; --i) {
277 *i = std::move(*(i - 1));
278 }
279
280 position->~T();
281 ::new(position) T(std::forward<Args>(args)...);
282
283 return position;
284 }
285
287 auto dist = position - begin();
288 position->~T();
289
290 for(auto i = begin() + dist + 1; i != end(); ++i) {
291 *(i - 1) = std::move(*i);
292 }
293
294 resize(size() - 1);
295 return begin() + dist;
296 }
297
298 void resize(const size_type n) {
300
301 while(m_size > n) {
302 pop_back();
303 }
304
305 while(n > m_size) {
306 emplace_back();
307 }
308 }
309
313
314 if(v.m_size > m_size) {
315 longer = &v;
316 shorter = this;
317 } else {
318 longer = this;
319 shorter = &v;
320 }
321
322 for(size_t i = 0; i < shorter->size(); ++i) {
323 std::swap(shorter->at(i), longer->at(i));
324 }
325
326 auto short_size = shorter->m_size;
327
328 for(size_t i = shorter->size(); i < longer->size(); ++i) {
329 shorter->emplace_back(std::move(longer->at(i)));
330 longer->at(i).~T();
331 }
332
333 longer->m_size = short_size;
334 }
335
336 private:
337 typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type m_data[Capacity];
338 size_t m_size = 0;
339 };
340
341 template<typename T, size_t CapacityA, size_t CapacityB>
343 if(a.size() != b.size()) {
344 return false;
345 }
346
347 for(size_t i = 0; i < a.size(); ++i) {
348 if(a[i] != b[i]) {
349 return false;
350 }
351 }
352
353 return true;
354 }
355
356 template<typename T, size_t CapacityA, size_t CapacityB>
358 if(a.size() != b.size()) {
359 return true;
360 }
361
362 for(size_t i = 0; i < a.size(); ++i) {
363 if(a[i] != b[i]) {
364 return true;
365 }
366 }
367
368 return false;
369 }
370
371} // namespace CeresEngine
372
373template<typename T, size_t N> struct std::hash<CeresEngine::StaticVector<T, N>> {
375 constexpr size_t operator()(const Type& obj) const {
376 size_t seed = CeresEngine::hash(obj.size());
377 for(const T& value : obj) {
378 CeresEngine::combine(seed, value);
379 }
380 return seed;
381 }
382};
#define CE_STATIC_VECTOR_OUT_OF_RANGE_IF(cond, rescue_return)
Definition StaticVector.hpp:37
#define CE_STATIC_VECTOR_BOUNDS_CHECK(i)
Definition StaticVector.hpp:74
Definition Application.hpp:19
constexpr void combine(std::size_t &seed, const T &v)
Generates a new hash for the provided type using the default standard hasher and combines it with a p...
Definition Hash.hpp:32
bool operator!=(const ShortAllocator< T, N, A1 > &x, const ShortAllocator< U, M, A2 > &y) noexcept
Definition Allocator.hpp:416
bool operator==(const ShortAllocator< T, N, A1 > &x, const ShortAllocator< U, M, A2 > &y) noexcept
Definition Allocator.hpp:411
constexpr CountAlgorithmFunctor count
Returns the number of elements matching an element.
Definition Count.hpp:82
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition StaticVector.hpp:85
T * pointer
Definition StaticVector.hpp:87
T value_type
Definition StaticVector.hpp:86
const T * const_pointer
Definition StaticVector.hpp:88
StaticVector is almost a drop-in replacement of std::vector, but has a fixed capacity as a template a...
Definition StaticVector.hpp:84
StaticVector(const StaticVector &v)
Definition StaticVector.hpp:125
reference operator[](const size_type i)
Definition StaticVector.hpp:183
const_reverse_iterator rend() const noexcept
Definition StaticVector.hpp:205
StaticVector & operator=(const StaticVector &v)
Definition StaticVector.hpp:148
const_iterator begin() const noexcept
Definition StaticVector.hpp:196
const_reverse_iterator rbegin() const noexcept
Definition StaticVector.hpp:202
iterator erase(const_iterator position)
Definition StaticVector.hpp:286
size_t m_size
Definition StaticVector.hpp:338
reference front()
Definition StaticVector.hpp:186
T value_type
Definition StaticVector.hpp:92
iterator begin() noexcept
Definition StaticVector.hpp:195
size_t max_size() const noexcept
Definition StaticVector.hpp:211
const_pointer data() const noexcept
Definition StaticVector.hpp:191
const_reference at(size_type i) const
Definition StaticVector.hpp:172
StaticVector(std::initializer_list< T > l)
Definition StaticVector.hpp:117
const_reference operator[](const size_type i) const
Definition StaticVector.hpp:182
const_reverse_iterator crend() const noexcept
Definition StaticVector.hpp:206
T * pointer
Definition StaticVector.hpp:97
iterator insert(iterator position, const value_type &val)
Definition StaticVector.hpp:247
reference at(size_type i)
Definition StaticVector.hpp:177
StaticVector(StaticVector &&v) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition StaticVector.hpp:139
std::reverse_iterator< iterator > reverse_iterator
Definition StaticVector.hpp:101
const_iterator cbegin() const noexcept
Definition StaticVector.hpp:197
size_t size() const noexcept
Definition StaticVector.hpp:210
StaticVector(const size_t count, const T &value)
Definition StaticVector.hpp:109
void swap(StaticVector &v)
Definition StaticVector.hpp:310
ptrdiff_t difference_type
Definition StaticVector.hpp:94
pointer data() noexcept
Definition StaticVector.hpp:192
bool empty() const noexcept
Definition StaticVector.hpp:209
const T * const_pointer
Definition StaticVector.hpp:98
void clear() noexcept
Definition StaticVector.hpp:220
~StaticVector()
Definition StaticVector.hpp:146
const T & const_reference
Definition StaticVector.hpp:96
void emplace_back(Args &&... args)
Definition StaticVector.hpp:240
const_reference back() const
Definition StaticVector.hpp:188
size_t capacity() const noexcept
Definition StaticVector.hpp:212
iterator emplace(iterator position, Args &&... args)
Definition StaticVector.hpp:266
const_reference front() const
Definition StaticVector.hpp:185
void push_back(T &&v)
Definition StaticVector.hpp:233
void push_back(const_reference v)
Definition StaticVector.hpp:226
StaticVector & operator=(StaticVector &&v) noexcept(std::is_nothrow_move_assignable< T >::value)
Definition StaticVector.hpp:162
iterator end() noexcept
Definition StaticVector.hpp:198
T * iterator
Definition StaticVector.hpp:99
reverse_iterator rend() noexcept
Definition StaticVector.hpp:204
StaticVector(const StaticVector< T, CapacityB > &v)
Definition StaticVector.hpp:131
const_iterator end() const noexcept
Definition StaticVector.hpp:199
const_iterator cend() const noexcept
Definition StaticVector.hpp:200
StaticVector(const size_t count)
Definition StaticVector.hpp:107
T & reference
Definition StaticVector.hpp:95
reverse_iterator rbegin() noexcept
Definition StaticVector.hpp:201
const T * const_iterator
Definition StaticVector.hpp:100
void pop_back()
Definition StaticVector.hpp:215
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition StaticVector.hpp:102
size_t size_type
Definition StaticVector.hpp:93
const_reverse_iterator crbegin() const noexcept
Definition StaticVector.hpp:203
reference back()
Definition StaticVector.hpp:189
std::aligned_storage< sizeof(T), std::alignment_of< T >::value >::type m_data[Capacity]
Definition StaticVector.hpp:337
void resize(const size_type n)
Definition StaticVector.hpp:298