AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AStaticVector.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include "AVector.h"
15#include "AException.h"
16#include <utility>
17#include <span>
18
19
20#define AUI_ASSERT_MY_ITERATOR(it) AUI_ASSERTX((this->begin() <= it && it <= this->end()), "foreign iterator")
21
32template<typename StoredType, std::size_t MaxSize>
33class AStaticVector {
34public:
35 using self = AStaticVector;
36 using super = AStaticVector;
37 using iterator = StoredType*;
38 using const_iterator = const StoredType*;
39 using reference = StoredType&;
40 using const_reference = const StoredType&;
41 using value = StoredType;
42
43 constexpr AStaticVector() noexcept: mBegin(reinterpret_cast<StoredType*>(&mStorage)), mEnd(mBegin) {}
44 constexpr AStaticVector(const AStaticVector& rhs): AStaticVector() {
45 insert(mBegin, rhs.begin(), rhs.end());
46 }
47 constexpr AStaticVector(AStaticVector&& rhs) noexcept: AStaticVector() {
48 insert(mBegin, std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
49 rhs.clear();
50 }
51 constexpr AStaticVector(std::initializer_list<StoredType> rhs) noexcept: AStaticVector() {
52 insert(mBegin, std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
53 }
54 template<typename Iterator>
55 constexpr AStaticVector(Iterator begin, Iterator end) noexcept: AStaticVector() {
56 for (auto it = begin; it != end; ++it) { // range-v3 fix: basic range traversal instead of insert
57 push_back(*it);
58 }
59 }
60 constexpr ~AStaticVector() {
61 for (auto& v : *this) {
62 v.~StoredType();
63 }
64 }
65
66 [[nodiscard]]
67 static constexpr size_t capacity() noexcept {
68 return MaxSize;
69 }
70
71 AStaticVector& operator=(const AStaticVector& rhs) {
72 if (this == &rhs) {
73 return *this;
74 }
75 clear();
76 insert(mBegin, rhs.begin(), rhs.end());
77 return *this;
78 }
79
80 AStaticVector& operator=(AStaticVector&& rhs) noexcept {
81 if (this == &rhs) {
82 return *this;
83 }
84 clear();
85 insert(mBegin, std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
86 rhs.clear();
87 return *this;
88 }
89
90 [[nodiscard]]
91 constexpr bool full() const noexcept {
92 return size() >= MaxSize;
93 }
94
95 [[nodiscard]]
96 constexpr StoredType* data() noexcept {
97 return mBegin;
98 }
99 [[nodiscard]]
100 constexpr const StoredType* data() const noexcept {
101 return mBegin;
102 }
103
104 [[nodiscard]]
105 constexpr iterator begin() noexcept {
106 return mBegin;
107 }
108 [[nodiscard]]
109 constexpr const_iterator begin() const noexcept {
110 return mBegin;
111 }
112
113 [[nodiscard]]
114 constexpr iterator end() noexcept {
115 return mEnd;
116 }
117
118 [[nodiscard]]
119 constexpr const_iterator end() const noexcept {
120 return mEnd;
121 }
122
123 [[nodiscard]]
124 constexpr StoredType& front() noexcept {
125 return *begin();
126 }
127
128 [[nodiscard]]
129 constexpr StoredType& back() noexcept {
130 return *std::prev(end());
131 }
132
133 [[nodiscard]]
134 constexpr const StoredType& front() const noexcept {
135 return *begin();
136 }
137
138 [[nodiscard]]
139 constexpr const StoredType& back() const noexcept {
140 return *std::prev(end());
141 }
142
143 template<typename... Args>
144 constexpr void emplace_back(Args&&... args) noexcept {
145 AUI_ASSERTX(!full(), "insufficient size in AStaticVector");
146 new (mEnd++) StoredType(std::forward<Args>(args)...);
147 }
148
149
150 constexpr void push_back(StoredType value) noexcept {
151 AUI_ASSERTX(!full(), "insufficient size in AStaticVector");
152 new (mEnd++) StoredType(std::move(value));
153 }
154
155 constexpr void push_front(StoredType value) noexcept {
156 AUI_ASSERTX(!full(), "insufficient size in AStaticVector");
157 insert(begin(), std::move(value));
158 }
159
160 constexpr void pop_back() noexcept {
161 AUI_ASSERTX(size() > 0, "AStaticVector is empty");
162 erase(std::prev(end()));
163 }
164 constexpr void pop_front() noexcept {
165 AUI_ASSERTX(size() > 0, "AStaticVector is empty");
166 erase(begin());
167 }
168
169 [[nodiscard]]
170 constexpr StoredType& operator[](std::size_t index) noexcept {
171 AUI_ASSERTX(index < size(), "out of bounds");
172 return *(data() + index);
173 }
174
175 [[nodiscard]]
176 constexpr StoredType& operator[](std::size_t index) const noexcept {
177 return const_cast<AStaticVector*>(this)->operator[](index);
178 }
179
180 [[nodiscard]]
181 constexpr bool empty() const noexcept {
182 return begin() == end();
183 }
184
185 constexpr void clear() noexcept {
186 for (auto& v : *this) {
187 v.~StoredType();
188 }
189 mEnd = mBegin;
190 }
191
192 [[nodiscard]]
193 constexpr std::size_t size() const noexcept {
194 return mEnd - mBegin;
195 }
196
197 template<typename OtherIterator>
198 constexpr iterator insert(iterator at, OtherIterator begin, OtherIterator end) {
199 AUI_ASSERT_MY_ITERATOR(at);
200 auto distance = std::distance(begin, end);
201 AUI_ASSERTX(size() + distance <= MaxSize, "out of bounds");
202
203 return aui::container::vector_impl::insert_no_growth(mEnd, at, begin, end);
204 }
205
206 constexpr iterator insert(iterator at, StoredType value) {
207 AUI_ASSERT_MY_ITERATOR(at);
208 return insert(at, std::make_move_iterator(&value), std::make_move_iterator(&value + 1));
209 }
210
211 constexpr iterator erase(iterator at) {
212 return erase(at, std::next(at));
213 }
214
215 constexpr iterator erase(iterator begin, iterator end) {
216 AUI_ASSERT_MY_ITERATOR(begin);
217 AUI_ASSERT_MY_ITERATOR(end);
218
219 return aui::container::vector_impl::erase(mBegin, mEnd, begin, end);
220 }
221
222 void reserve(std::size_t) {
223 // does nothing - just for std::vector compatibility
224 }
225
226 // AUI extensions - see AVector for reference
227
228
235 template<typename OtherContainer>
236 iterator insertAll(const OtherContainer& c) noexcept {
237 return insertAll(super::end(), c);
238 }
239
240
247 template<typename OtherContainer>
248 iterator insertAll(OtherContainer&& c) noexcept {
249 return insertAll(super::end(), std::forward<OtherContainer>(c));
250 }
251
252
260 template<typename OtherContainer>
261 iterator insertAll(iterator at, const OtherContainer& c) noexcept {
262 return super::insert(at, c.begin(), c.end());
263 }
264
265
273 template<typename OtherContainer>
274 iterator insertAll(iterator at, OtherContainer&& c) noexcept {
275 return super::insert(at, std::make_move_iterator(c.begin()), std::make_move_iterator(c.end()));
276 }
277
278
283 void removeAll(const StoredType& item) noexcept
284 {
285 aui::container::remove_all(*this, item);
286 }
287
292 void removeFirst(const StoredType& item) noexcept
293 {
294 aui::container::remove_first(*this, item);
295 }
296
297
301 template<typename OtherContainer>
302 bool isSubsetOf(const OtherContainer& c) const noexcept
303 {
304 return aui::container::is_subset(*this, c);
305 }
306
310 bool contains(const StoredType& value) const noexcept {
311 return aui::container::contains(*this, value);
312 }
313
314 [[nodiscard]]
315 std::size_t sizeInBytes() const noexcept {
316 return super::size() * sizeof(StoredType);
317 }
318
319 [[nodiscard]]
320 StoredType& at(std::size_t index) {
321 if (index >= super::size()) {
322 aui::impl::outOfBoundsException();
323 }
324 return super::operator[](index);
325 }
326
327 [[nodiscard]]
328 const StoredType& at(std::size_t index) const {
329 if (index >= super::size()) {
330 aui::impl::outOfBoundsException();
331 }
332 return super::operator[](index);
333 }
334
335
341 self& operator<<(const StoredType& rhs) noexcept
342 {
343 super::push_back(rhs);
344 return *this;
345 }
346
352 self& operator<<(StoredType&& rhs) noexcept
353 {
354 super::push_back(std::forward<StoredType>(rhs));
355 return *this;
356 }
357
363 template<typename OtherContainer, std::enable_if_t<!std::is_convertible_v<OtherContainer, StoredType>, bool> = true>
364 self& operator<<(const OtherContainer& c) noexcept
365 {
366 insertAll(c);
367 return *this;
368 }
369
375 template<typename OtherContainer, std::enable_if_t<!std::is_convertible_v<OtherContainer, StoredType>, bool> = true>
376 self& operator<<(OtherContainer&& c) noexcept
377 {
378 insertAll(std::forward<OtherContainer>(c));
379 return *this;
380 }
381
382
390 StoredType& first() noexcept
391 {
392 AUI_ASSERTX(!super::empty(), "empty container could not have the first element");
393 return super::front();
394 }
395
403 const StoredType& first() const noexcept
404 {
405 AUI_ASSERTX(!super::empty(), "empty container could not have the first element");
406 return super::front();
407 }
408
416 StoredType& last() noexcept
417 {
418 AUI_ASSERTX(!super::empty(), "empty container could not have the last element");
419 return super::back();
420 }
421
429 const StoredType& last() const noexcept
430 {
431 AUI_ASSERTX(!super::empty(), "empty container could not have the last element");
432 return super::back();
433 }
434
439 [[nodiscard]]
440 AOptional<size_t> indexOf(const StoredType& value) const noexcept
441 {
442 return aui::container::index_of(*this, value);
443 }
444
445
446 void sort() noexcept {
447 std::sort(super::begin(), super::end());
448 }
449
450 template<typename Comparator>
451 void sort(Comparator&& comparator) noexcept {
452 std::sort(super::begin(), super::end(), std::forward<Comparator>(comparator));
453 }
454
463 void removeAt(size_t index) noexcept
464 {
465 aui::container::remove_at(*this, index);
466 }
467
472 template<typename Predicate>
473 void removeIf(Predicate&& predicate) noexcept
474 {
475 super::erase(std::remove_if(super::begin(), super::end(), std::forward<Predicate>(predicate)), super::end());
476 }
477
478 ASet<StoredType> toSet() const noexcept {
479 return ASet<StoredType>(super::begin(), super::end());
480 }
481
488 template<aui::incrementable Iterator, aui::invocable<decltype(*std::declval<Iterator>())> UnaryOperation>
489 static auto fromRange(aui::range<Iterator> range, UnaryOperation&& transformer) -> AVector<decltype(transformer(range.first()))> {
490 AVector<decltype(transformer(range.first()))> result;
491 result.reserve(range.size());
492 std::transform(range.begin(), range.end(), std::back_inserter(result), std::forward<UnaryOperation>(transformer));
493 return result;
494 }
495
496 template<aui::invocable<const StoredType&> UnaryOperation>
497 auto map(UnaryOperation&& transformer) const -> AVector<decltype(transformer(std::declval<StoredType>()))> {
499 result.reserve(super::size());
500 std::transform(super::begin(), super::end(), std::back_inserter(result), std::forward<UnaryOperation>(transformer));
501 return result;
502 }
503
504 template<aui::invocable<const StoredType&> UnaryOperation>
505 [[nodiscard]]
506 auto toMap(UnaryOperation&& transformer) const -> AMap<decltype(transformer(std::declval<StoredType>()).first),
507 decltype(transformer(std::declval<StoredType>()).second)> {
508 return aui::container::to_map(super::begin(), super::end(), transformer);
509 }
510
511 template<aui::invocable<StoredType&> UnaryOperation>
512 [[nodiscard]]
513 auto toMap(UnaryOperation&& transformer) -> AMap<decltype(transformer(std::declval<StoredType>()).first),
514 decltype(transformer(std::declval<StoredType>()).second)> {
515 return aui::container::to_map(super::begin(), super::end(), transformer);
516 }
517
518 template<aui::predicate<const StoredType&> Predicate>
519 self filter(Predicate&& predicate) {
520 self result;
521 result.reserve(super::size());
522 for (const auto& element : *this) {
523 if (predicate(element)) {
524 result.push_back(element);
525 }
526 }
527 return result;
528 }
529
530 [[nodiscard]]
531 operator std::span<StoredType>() {
532 return std::span(data(), size());
533 }
534
535 [[nodiscard]]
536 operator std::span<const StoredType>() const {
537 return std::span(data(), size());
538 }
539
540private:
541 iterator mBegin;
542 iterator mEnd;
543 std::aligned_storage_t<sizeof(StoredType) * MaxSize, alignof(StoredType)> mStorage;
544};
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:32
A std::set with AUI extensions.
Definition ASet.h:25
StoredType & first() noexcept
Definition AStaticVector.h:390
iterator insertAll(iterator at, const OtherContainer &c) noexcept
Definition AStaticVector.h:261
void removeAt(size_t index) noexcept
Definition AStaticVector.h:463
self & operator<<(const StoredType &rhs) noexcept
Definition AStaticVector.h:341
void removeFirst(const StoredType &item) noexcept
Definition AStaticVector.h:292
void removeAll(const StoredType &item) noexcept
Definition AStaticVector.h:283
self & operator<<(StoredType &&rhs) noexcept
Definition AStaticVector.h:352
AOptional< size_t > indexOf(const StoredType &value) const noexcept
Definition AStaticVector.h:440
const StoredType & first() const noexcept
Definition AStaticVector.h:403
bool contains(const StoredType &value) const noexcept
Definition AStaticVector.h:310
iterator insertAll(OtherContainer &&c) noexcept
Definition AStaticVector.h:248
iterator insertAll(const OtherContainer &c) noexcept
Definition AStaticVector.h:236
void removeIf(Predicate &&predicate) noexcept
Definition AStaticVector.h:473
self & operator<<(OtherContainer &&c) noexcept
Definition AStaticVector.h:376
const StoredType & last() const noexcept
Definition AStaticVector.h:429
self & operator<<(const OtherContainer &c) noexcept
Definition AStaticVector.h:364
static auto fromRange(aui::range< Iterator > range, UnaryOperation &&transformer) -> AVector< decltype(transformer(range.first()))>
Constructs a new vector of transformed items of the range.
Definition AStaticVector.h:489
StoredType & last() noexcept
Definition AStaticVector.h:416
bool isSubsetOf(const OtherContainer &c) const noexcept
Definition AStaticVector.h:302
iterator insertAll(iterator at, OtherContainer &&c) noexcept
Definition AStaticVector.h:274
A std::vector with AUI extensions.
Definition AVector.h:39
bool is_subset(LContainer &l, RContainer &r) noexcept
Definition containers.h:204
AOptional< size_t > index_of(const Container &c, const typename Container::const_reference value) noexcept
Finds the index of the first occurrence of the value.
Definition containers.h:112
bool contains(const Container &c, const typename Container::const_reference value) noexcept
Definition containers.h:124
AOptional< std::size_t > remove_first(Container &container, typename Container::const_reference value) noexcept
Removes first occurrence of value.
Definition containers.h:171
auto to_map(Iterator begin, Iterator end, UnaryOperation &&transformer)
Transforms sequence to map.
Definition AMap.h:237
void remove_at(Container &c, size_t index) noexcept
Removes element at the specified index.
Definition containers.h:98
void remove_all(Container &container, typename Container::const_reference value) noexcept
Removes all occurrences of value.
Definition containers.h:143
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74
Definition iterators.h:50