Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
static_vector.hpp
Go to the documentation of this file.
1
10
11#pragma once
12
13#include <cstddef>
14#include <iterator>
15#include <stdexcept>
16#include <type_traits>
18#include <utility>
19
24template <typename T, std::size_t MaxSize> class static_vector {
25 public:
26 using value_type = T;
27 using size_type = std::size_t;
28 using difference_type = std::ptrdiff_t;
29 using reference = T&;
30 using const_reference = T const&;
31 using pointer = T*;
32 using const_pointer = T const*;
33 using iterator = T*;
34 using const_iterator = T const*;
35 using reverse_iterator = std::reverse_iterator<iterator>;
36 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
37
39 static_vector() noexcept : size_(0) {}
40
43 explicit static_vector(size_type count) : size_(count)
44 {
45 DEBUG_PRECONDITION(count <= MaxSize);
46 for (size_type i = 0; i < size_; ++i)
47 {
48 ::new (data() + i) T();
49 }
50 }
51
53 static_vector(size_type count, T const& value) : size_(count)
54 {
55 DEBUG_PRECONDITION(count <= MaxSize);
56 for (size_type i = 0; i < size_; ++i)
57 {
58 ::new (data() + i) T(value);
59 }
60 }
61
63 static_vector(std::initializer_list<T> init) : size_(init.size())
64 {
65 DEBUG_PRECONDITION(init.size() <= MaxSize);
66 size_type i = 0;
67 for (T const& v : init)
68 {
69 ::new (data() + i++) T(v);
70 }
71 }
72
74 static_vector(static_vector const& o) : size_(o.size_)
75 {
76 for (size_type i = 0; i < size_; ++i)
77 {
78 ::new (data() + i) T(o.data()[i]);
79 }
80 }
81
83 static_vector(static_vector&& o) noexcept(std::is_nothrow_move_constructible<T>::value) : size_(o.size_)
84 {
85 for (size_type i = 0; i < size_; ++i)
86 {
87 ::new (data() + i) T(std::move(o.data()[i]));
88 o.data()[i].~T();
89 }
90 o.size_ = 0;
91 }
92
95
98 {
99 if (this != &o)
100 {
101 clear();
102 size_ = o.size_;
103 for (size_type i = 0; i < size_; ++i)
104 {
105 ::new (data() + i) T(o.data()[i]);
106 }
107 }
108 return *this;
109 }
110
112 static_vector& operator=(static_vector&& o) noexcept(std::is_nothrow_move_assignable<T>::value)
113 {
114 if (this != &o)
115 {
116 clear();
117 size_ = o.size_;
118 for (size_type i = 0; i < size_; ++i)
119 {
120 ::new (data() + i) T(std::move(o.data()[i]));
121 o.data()[i].~T();
122 }
123 o.size_ = 0;
124 }
125 return *this;
126 }
127
129 static_vector& operator=(std::initializer_list<T> init)
130 {
131 clear();
132 size_ = init.size();
133 DEBUG_PRECONDITION(size_ <= MaxSize);
134 size_type i = 0;
135 for (T const& v : init)
136 {
137 ::new (data() + i++) T(v);
138 }
139 return *this;
140 }
141
143 [[nodiscard]] reference at(size_type pos)
144 {
145 if (pos >= size_) throw std::out_of_range("static_vector::at");
146 return data()[pos];
147 }
148
149 [[nodiscard]] const_reference at(size_type pos) const
150 {
151 if (pos >= size_) throw std::out_of_range("static_vector::at");
152 return data()[pos];
153 }
154
156 {
157 DEBUG_PRECONDITION(pos < size_);
158 return data()[pos];
159 }
160
162 {
163 DEBUG_PRECONDITION(pos < size_);
164 return data()[pos];
165 }
166
167 [[nodiscard]] reference front()
168 {
169 DEBUG_PRECONDITION(size_ > 0);
170 return data()[0];
171 }
172
173 [[nodiscard]] const_reference front() const
174 {
175 DEBUG_PRECONDITION(size_ > 0);
176 return data()[0];
177 }
178
179 [[nodiscard]] reference back()
180 {
181 DEBUG_PRECONDITION(size_ > 0);
182 return data()[size_ - 1];
183 }
184
185 [[nodiscard]] const_reference back() const
186 {
187 DEBUG_PRECONDITION(size_ > 0);
188 return data()[size_ - 1];
189 }
190
191 [[nodiscard]] pointer data() noexcept { return reinterpret_cast<T*>(storage_.buf); }
192 [[nodiscard]] const_pointer data() const noexcept { return reinterpret_cast<T const*>(storage_.buf); }
193
194 [[nodiscard]] iterator begin() noexcept { return data(); }
195 [[nodiscard]] const_iterator begin() const noexcept { return data(); }
196 [[nodiscard]] const_iterator cbegin() const noexcept { return data(); }
197
198 [[nodiscard]] iterator end() noexcept { return data() + size_; }
199 [[nodiscard]] const_iterator end() const noexcept { return data() + size_; }
200 [[nodiscard]] const_iterator cend() const noexcept { return data() + size_; }
201
202 [[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
203 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
204 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
205
206 [[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
207 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
208 [[nodiscard]] const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
209
210 [[nodiscard]] bool empty() const noexcept { return size_ == 0; }
211 [[nodiscard]] size_type size() const noexcept { return size_; }
212 static constexpr size_type max_size() noexcept { return MaxSize; }
213 static constexpr size_type capacity() noexcept { return MaxSize; }
214
216 void clear() noexcept
217 {
218 for (size_type i = 0; i < size_; ++i)
219 {
220 data()[i].~T();
221 }
222 size_ = 0;
223 }
224
226 void push_back(T const& value)
227 {
228 DEBUG_PRECONDITION(size_ < MaxSize);
229 ::new (data() + size_) T(value);
230 ++size_;
231 }
232
234 void push_back(T&& value)
235 {
236 DEBUG_PRECONDITION(size_ < MaxSize);
237 ::new (data() + size_) T(std::move(value));
238 ++size_;
239 }
240
242 template <class... Args> void emplace_back(Args&&... args)
243 {
244 DEBUG_PRECONDITION(size_ < MaxSize);
245 ::new (data() + size_) T(std::forward<Args>(args)...);
246 ++size_;
247 }
248
250 void pop_back()
251 {
252 DEBUG_PRECONDITION(size_ > 0);
253 data()[--size_].~T();
254 }
255
257 void resize(size_type count)
258 {
259 DEBUG_PRECONDITION(count <= MaxSize);
260 if (count < size_)
261 {
262 for (size_type i = count; i < size_; ++i)
263 {
264 data()[i].~T();
265 }
266 }
267 else
268 {
269 for (size_type i = size_; i < count; ++i)
270 {
271 ::new (data() + i) T();
272 }
273 }
274 size_ = count;
275 }
276
278 void swap(static_vector& other) noexcept(std::is_nothrow_swappable<T>::value)
279 {
280 size_type m = size_ < other.size_ ? size_ : other.size_;
281 for (size_type i = 0; i < m; ++i)
282 {
283 using std::swap;
284 swap(data()[i], other.data()[i]);
285 }
286 if (size_ < other.size_)
287 {
288 for (size_type i = m; i < other.size_; ++i)
289 {
290 emplace_back(std::move(other.data()[i]));
291 }
292 other.resize(m);
293 }
294 else if (size_ > other.size_)
295 {
296 for (size_type i = m; i < size_; ++i)
297 {
298 other.emplace_back(std::move(data()[i]));
299 }
300 resize(m);
301 }
302 }
303
304 private:
305 struct Storage
306 {
307 alignas(T) unsigned char buf[MaxSize * sizeof(T)];
308 } storage_;
309 size_type size_;
310};
311
316template <typename T> class static_vector<T, 0> {
317 public:
318 using value_type = T;
319 using size_type = std::size_t;
320 using difference_type = std::ptrdiff_t;
321 using reference = T&;
322 using const_reference = T const&;
323 using pointer = T*;
324 using const_pointer = T const*;
325 using iterator = T*;
326 using const_iterator = T const*;
327 using reverse_iterator = std::reverse_iterator<iterator>;
328 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
329
330 static_vector() noexcept = default;
331 explicit static_vector(size_type count) { DEBUG_CHECK_EQUAL(count, 0); }
332 static_vector(size_type count, T const&) { DEBUG_CHECK_EQUAL(count, 0); }
333 static_vector(std::initializer_list<T> init) { DEBUG_CHECK_EQUAL(init.size(), 0); }
334
335 static_vector(static_vector const&) = default;
336 static_vector(static_vector&&) noexcept = default;
337 static_vector& operator=(static_vector const&) = default;
338 static_vector& operator=(static_vector&&) noexcept = default;
339 static_vector& operator=(std::initializer_list<T> init)
340 {
341 DEBUG_CHECK_EQUAL(init.size(), 0);
342 return *this;
343 }
344
345 [[nodiscard]] constexpr bool empty() const noexcept { return true; }
346 [[nodiscard]] constexpr size_type size() const noexcept { return 0; }
347 static constexpr size_type max_size() noexcept { return 0; }
348 static constexpr size_type capacity() noexcept { return 0; }
349
350 void clear() noexcept {}
351 void resize(size_type count) { DEBUG_CHECK_EQUAL(count, 0); }
352
353 void push_back(T const&) { PANIC("unexpected: push_back() on a static_vector of size 0"); }
354 void push_back(T&&) { PANIC("unexpected: push_back() on a static_vector of size 0"); }
355 template <typename... Args> void emplace_back(Args&&...)
356 {
357 PANIC("unexpected: emplace_back() on a static_vector of size 0");
358 }
359 void pop_back() { PANIC("unexpected: pop_back() on a static_vector of size 0"); }
360
361 [[nodiscard]] reference at(size_type) { throw std::out_of_range("static_vector<..., 0>::at"); }
362 [[nodiscard]] const_reference at(size_type) const { throw std::out_of_range("static_vector<..., 0>::at"); }
363
364 reference operator[](size_type) { PANIC("unexpected: operator[] on a static_vector of size 0"); }
365 const_reference operator[](size_type) const { PANIC("unexpected: operator[] on a static_vector of size 0"); }
366
367 [[nodiscard]] reference front() { PANIC("unexpected: front() on a static_vector of size 0"); }
368 [[nodiscard]] const_reference front() const
369 {
370 PANIC("unexpected: front() on a static_vector of size 0");
371 std::abort();
372 }
373
374 [[nodiscard]] reference back()
375 {
376 PANIC("unexpected: back() on a static_vector of size 0");
377 std::abort();
378 }
379 [[nodiscard]] const_reference back() const
380 {
381 PANIC("unexpected: back() on a static_vector of size 0");
382 std::abort();
383 }
384
385 [[nodiscard]] pointer data() noexcept { return nullptr; }
386 [[nodiscard]] const_pointer data() const noexcept { return nullptr; }
387
388 [[nodiscard]] iterator begin() noexcept { return nullptr; }
389 [[nodiscard]] const_iterator begin() const noexcept { return nullptr; }
390 [[nodiscard]] const_iterator cbegin() const noexcept { return nullptr; }
391
392 [[nodiscard]] iterator end() noexcept { return nullptr; }
393 [[nodiscard]] const_iterator end() const noexcept { return nullptr; }
394 [[nodiscard]] const_iterator cend() const noexcept { return nullptr; }
395
396 [[nodiscard]] reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
397 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
398 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
399
400 [[nodiscard]] reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
401 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
402 [[nodiscard]] const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
403
404 void swap(static_vector&) noexcept {}
405
406 private:
407 // no storage
408};
std::reverse_iterator< iterator > reverse_iterator
Definition static_vector.hpp:327
const_reverse_iterator crbegin() const noexcept
Definition static_vector.hpp:398
static constexpr size_type max_size() noexcept
Definition static_vector.hpp:347
std::size_t size_type
Definition static_vector.hpp:319
iterator begin() noexcept
Definition static_vector.hpp:388
void push_back(T const &)
Definition static_vector.hpp:353
void resize(size_type count)
Definition static_vector.hpp:351
const_reference front() const
Definition static_vector.hpp:368
T & reference
Definition static_vector.hpp:321
const_reverse_iterator rend() const noexcept
Definition static_vector.hpp:401
constexpr bool empty() const noexcept
Definition static_vector.hpp:345
reference front()
Definition static_vector.hpp:367
const_iterator cbegin() const noexcept
Definition static_vector.hpp:390
constexpr size_type size() const noexcept
Definition static_vector.hpp:346
void pop_back()
Definition static_vector.hpp:359
iterator end() noexcept
Definition static_vector.hpp:392
const_reverse_iterator rbegin() const noexcept
Definition static_vector.hpp:397
T const * const_pointer
Definition static_vector.hpp:324
static_vector(size_type count, T const &)
Definition static_vector.hpp:332
reference operator[](size_type)
Definition static_vector.hpp:364
T const & const_reference
Definition static_vector.hpp:322
reference at(size_type)
Definition static_vector.hpp:361
void clear() noexcept
Definition static_vector.hpp:350
T value_type
Definition static_vector.hpp:318
void emplace_back(Args &&...)
Definition static_vector.hpp:355
const_reference operator[](size_type) const
Definition static_vector.hpp:365
const_reference at(size_type) const
Definition static_vector.hpp:362
static constexpr size_type capacity() noexcept
Definition static_vector.hpp:348
T * iterator
Definition static_vector.hpp:325
const_iterator cend() const noexcept
Definition static_vector.hpp:394
reference back()
Definition static_vector.hpp:374
void swap(static_vector &) noexcept
Definition static_vector.hpp:404
reverse_iterator rbegin() noexcept
Definition static_vector.hpp:396
const_iterator begin() const noexcept
Definition static_vector.hpp:389
static_vector(static_vector const &)=default
void push_back(T &&)
Definition static_vector.hpp:354
const_reverse_iterator crend() const noexcept
Definition static_vector.hpp:402
pointer data() noexcept
Definition static_vector.hpp:385
static_vector(std::initializer_list< T > init)
Definition static_vector.hpp:333
const_iterator end() const noexcept
Definition static_vector.hpp:393
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_vector.hpp:328
const_pointer data() const noexcept
Definition static_vector.hpp:386
static_vector() noexcept=default
T * pointer
Definition static_vector.hpp:323
T const * const_iterator
Definition static_vector.hpp:326
static_vector(static_vector &&) noexcept=default
const_reference back() const
Definition static_vector.hpp:379
reverse_iterator rend() noexcept
Definition static_vector.hpp:400
std::ptrdiff_t difference_type
Definition static_vector.hpp:320
A fixed-capacity vector with stack storage and std::vector-like API.
Definition static_vector.hpp:24
static constexpr size_type max_size() noexcept
Definition static_vector.hpp:212
const_reverse_iterator rend() const noexcept
Definition static_vector.hpp:207
T * pointer
Definition static_vector.hpp:31
static_vector & operator=(static_vector const &o)
Copy assignment.
Definition static_vector.hpp:97
static_vector & operator=(std::initializer_list< T > init)
Assign from an initializer list.
Definition static_vector.hpp:129
reverse_iterator rbegin() noexcept
Definition static_vector.hpp:202
size_type size() const noexcept
Definition static_vector.hpp:211
void pop_back()
Remove the last element.
Definition static_vector.hpp:250
const_reverse_iterator crbegin() const noexcept
Definition static_vector.hpp:204
void clear() noexcept
Destroy all elements and reset size to zero.
Definition static_vector.hpp:216
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_vector.hpp:36
iterator end() noexcept
Definition static_vector.hpp:198
const_reference at(size_type pos) const
Definition static_vector.hpp:149
const_iterator cbegin() const noexcept
Definition static_vector.hpp:196
const_reference back() const
Definition static_vector.hpp:185
void resize(size_type count)
Resize the vector to count elements.
Definition static_vector.hpp:257
T value_type
Definition static_vector.hpp:26
const_iterator begin() const noexcept
Definition static_vector.hpp:195
reference back()
Definition static_vector.hpp:179
static constexpr size_type capacity() noexcept
Definition static_vector.hpp:213
std::reverse_iterator< iterator > reverse_iterator
Definition static_vector.hpp:35
static_vector(std::initializer_list< T > init)
Construct from an initializer list.
Definition static_vector.hpp:63
reference at(size_type pos)
Bounds-checked element access.
Definition static_vector.hpp:143
pointer data() noexcept
Definition static_vector.hpp:191
bool empty() const noexcept
Definition static_vector.hpp:210
T & reference
Definition static_vector.hpp:29
static_vector(static_vector const &o)
Copy constructor.
Definition static_vector.hpp:74
static_vector & operator=(static_vector &&o) noexcept(std::is_nothrow_move_assignable< T >::value)
Move assignment.
Definition static_vector.hpp:112
reference front()
Definition static_vector.hpp:167
T const * const_pointer
Definition static_vector.hpp:32
std::ptrdiff_t difference_type
Definition static_vector.hpp:28
static_vector(static_vector &&o) noexcept(std::is_nothrow_move_constructible< T >::value)
Move constructor.
Definition static_vector.hpp:83
const_iterator end() const noexcept
Definition static_vector.hpp:199
void emplace_back(Args &&... args)
Construct a new element in-place at the end.
Definition static_vector.hpp:242
const_iterator cend() const noexcept
Definition static_vector.hpp:200
iterator begin() noexcept
Definition static_vector.hpp:194
const_reference operator[](size_type pos) const
Definition static_vector.hpp:161
void push_back(T &&value)
Append a new moved value to the end.
Definition static_vector.hpp:234
const_reverse_iterator rbegin() const noexcept
Definition static_vector.hpp:203
static_vector() noexcept
Default-construct an empty static_vector.
Definition static_vector.hpp:39
~static_vector()
Destructor. Destroys all elements in-place.
Definition static_vector.hpp:94
const_reference front() const
Definition static_vector.hpp:173
T const & const_reference
Definition static_vector.hpp:30
std::size_t size_type
Definition static_vector.hpp:27
T * iterator
Definition static_vector.hpp:33
void swap(static_vector &other) noexcept(std::is_nothrow_swappable< T >::value)
Swap contents with another static_vector.
Definition static_vector.hpp:278
const_pointer data() const noexcept
Definition static_vector.hpp:192
static_vector(size_type count, T const &value)
Construct with count copies of value.
Definition static_vector.hpp:53
reference operator[](size_type pos)
Definition static_vector.hpp:155
T const * const_iterator
Definition static_vector.hpp:34
reverse_iterator rend() noexcept
Definition static_vector.hpp:206
static_vector(size_type count)
Construct with count default-initialized elements.
Definition static_vector.hpp:43
const_reverse_iterator crend() const noexcept
Definition static_vector.hpp:208
void push_back(T const &value)
Append a new copy of value to the end.
Definition static_vector.hpp:226
locale_t value
Definition data_table.cpp:49
Definition qnum.hpp:403
#define DEBUG_PRECONDITION(cond,...)
Definition trace.hpp:648
#define PANIC(...)
Definition trace.hpp:382
#define DEBUG_CHECK_EQUAL(a, b,...)
Definition trace.hpp:618