stellarlib 0.1.0
Loading...
Searching...
No Matches
stack_vector.hpp
1/* clang-format off */
2
3/*
4 stellarlib
5 Copyright (C) 2025-2026 Domán Zana
6
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 2. Altered source versions must be plainly marked as such, and must not be
20 misrepresented as being the original software.
21 3. This notice may not be removed or altered from any source distribution.
22*/
23
24#ifndef STELLARLIB_ECS_STACK_VECTOR_HPP
25#define STELLARLIB_ECS_STACK_VECTOR_HPP
26
27#include <stellarlib/ext/memory.hpp>
28#include <stellarlib/ext/type_traits.hpp>
29
30#include <cstddef>
31#include <memory>
32#include <utility>
33
34namespace stellarlib::ecs::internal
35{
36template <typename T, typename SizeType = std::size_t>
37class stack_vector final : ext::vector_allocator<T, SizeType>
38{
39public:
40 [[nodiscard]]
41 constexpr stack_vector() noexcept = default;
42
43 [[nodiscard]]
44 constexpr stack_vector(const stack_vector &) noexcept = delete;
45
46 [[nodiscard]]
47 constexpr stack_vector(stack_vector &&other) noexcept
48 : _begin{std::exchange(other._begin, {})}
49 , _end{std::exchange(other._end, {})}
50 , _size{std::exchange(other._size, {})}
51 , _capacity{std::exchange(other._capacity, {})}
52 {}
53
54 constexpr auto operator=(const stack_vector &) noexcept
55 -> stack_vector & = delete;
56
57 constexpr auto operator=(stack_vector &&other) noexcept
58 -> auto &
59 {
60 if (std::addressof(other) != this) {
61 std::destroy_at(this);
62 std::construct_at(this, std::move(other));
63 }
64
65 return *this;
66 }
67
68 constexpr ~stack_vector() noexcept
69 {
70 std::ranges::destroy(*this);
72 }
73
74 template <typename ...Args>
75 constexpr void push(Args &&...args) noexcept
76 {
77 if (_size == _capacity) {
78 ext::vector_allocator<T, SizeType>::reallocate(_begin, _size, ++_capacity);
79 _end = _begin + _size;
80 }
81
82 ++_size;
83 std::construct_at(_end++, std::forward<Args>(args)...);
84 }
85
86 template <typename ...Args>
87 constexpr auto extend(const SizeType size, Args &&...args) noexcept
88 {
89 if (size <= _size) {
90 return false;
91 }
92
93 if (_capacity < size) {
94 _capacity = size;
95 ext::vector_allocator<T, SizeType>::reallocate(_begin, _size, _capacity);
96 }
97
98 _end = _begin + size;
99 std::uninitialized_fill(_begin + _size, _end, T{std::forward<Args>(args)...});
100 _size = size;
101 return true;
102 }
103
104 [[nodiscard]]
105 constexpr auto size() const noexcept
106 {
107 return _size;
108 }
109
110 [[nodiscard]]
111 constexpr auto operator[](const SizeType index) const noexcept
112 -> const auto &
113 {
114 return _begin[index];
115 }
116
117 [[nodiscard]]
118 constexpr auto operator[](const SizeType index) noexcept
119 -> auto &
120 {
121 return _begin[index];
122 }
123
124 [[nodiscard]]
125 constexpr auto begin() const noexcept
126 {
127 return static_cast<const T *>(_begin);
128 }
129
130 [[nodiscard]]
131 constexpr auto begin() noexcept
132 {
133 return _begin;
134 }
135
136 [[nodiscard]]
137 constexpr auto end() const noexcept
138 {
139 return static_cast<const T *>(_end);
140 }
141
142 [[nodiscard]]
143 constexpr auto end() noexcept
144 {
145 return _end;
146 }
147
148 constexpr void pop() noexcept
149 {
150 --_size;
151 std::destroy_at(--_end);
152 }
153
154 constexpr void clear() noexcept
155 {
156 std::ranges::destroy(*this);
157 _end = _begin;
158 _size = 0;
159 }
160
161private:
162 T *_begin{};
163 T *_end{};
164 SizeType _size{};
165 SizeType _capacity{};
166 [[no_unique_address]] ext::padding<T *, SizeType, SizeType> _padding;
167};
168}
169
170#endif
constexpr void reallocate(value_type *&begin, const size_type capacity) const noexcept
Reallocates uninitialized memory for N instances of type T via bit-wise relocation.
Definition memory.hpp:128
constexpr void deallocate(value_type *begin) const noexcept
Deallocates uninitialized memory.
Definition memory.hpp:172