BCNP 3.2.1
Batched Command Network Protocol
Loading...
Searching...
No Matches
static_vector.h
Go to the documentation of this file.
1#pragma once
2
11#include <cstddef>
12#include <initializer_list>
13#include <new>
14#include <stdexcept>
15#include <type_traits>
16#include <utility>
17
18namespace bcnp {
19
28template <typename T, std::size_t Capacity>
30public:
31 using value_type = T;
32 using size_type = std::size_t;
33 using iterator = T*;
34 using const_iterator = const T*;
35
37 StaticVector() noexcept = default;
38
44 StaticVector(std::initializer_list<T> init) {
45 if (init.size() > Capacity) {
46 throw std::out_of_range("StaticVector initializer list too large");
47 }
48 for (const auto& value : init) {
49 push_back(value);
50 }
51 }
52
57 StaticVector(const StaticVector& other) : m_size(0) {
58 for (size_type i = 0; i < other.m_size; ++i) {
59 push_back(other[i]);
60 }
61 }
62
67 StaticVector(StaticVector&& other) noexcept(std::is_nothrow_move_constructible_v<T>)
68 : m_size(0) {
69 for (size_type i = 0; i < other.m_size; ++i) {
70 emplace_back(std::move(other[i]));
71 }
72 other.clear();
73 }
74
81 if (this != &other) {
82 clear();
83 for (size_type i = 0; i < other.m_size; ++i) {
84 push_back(other[i]);
85 }
86 }
87 return *this;
88 }
89
96 std::is_nothrow_move_constructible_v<T> && std::is_nothrow_destructible_v<T>) {
97 if (this != &other) {
98 clear();
99 for (size_type i = 0; i < other.m_size; ++i) {
100 emplace_back(std::move(other[i]));
101 }
102 other.clear();
103 }
104 return *this;
105 }
106
109
111 size_type size() const noexcept { return m_size; }
112
114 constexpr size_type capacity() const noexcept { return Capacity; }
115
117 bool empty() const noexcept { return m_size == 0; }
118
121 iterator begin() noexcept { return data(); }
122 iterator end() noexcept { return data() + m_size; }
123 const_iterator begin() const noexcept { return data(); }
124 const_iterator end() const noexcept { return data() + m_size; }
125 const_iterator cbegin() const noexcept { return data(); }
126 const_iterator cend() const noexcept { return data() + m_size; }
134 T& operator[](size_type index) noexcept { return data()[index]; }
135
137 const T& operator[](size_type index) const noexcept { return data()[index]; }
138
145 T& at(size_type index) {
146 if (index >= m_size) {
147 throw std::out_of_range("StaticVector index out of range");
148 }
149 return data()[index];
150 }
151
153 const T& at(size_type index) const {
154 if (index >= m_size) {
155 throw std::out_of_range("StaticVector index out of range");
156 }
157 return data()[index];
158 }
159
161 T& front() noexcept { return data()[0]; }
163 const T& front() const noexcept { return data()[0]; }
164
166 T& back() noexcept { return data()[m_size - 1]; }
168 const T& back() const noexcept { return data()[m_size - 1]; }
169
171 T* data() noexcept { return std::launder(reinterpret_cast<T*>(m_storage)); }
173 const T* data() const noexcept { return std::launder(reinterpret_cast<const T*>(m_storage)); }
174
181 void clear() noexcept {
182 T* storage = data();
183 for (size_type i = m_size; i > 0; --i) {
184 storage[i - 1].~T();
185 }
186 m_size = 0;
187 }
188
194 void push_back(const T& value) {
195 if (m_size >= Capacity) {
196 throw std::out_of_range("StaticVector capacity exceeded");
197 }
198 new (data() + m_size) T(value);
199 ++m_size;
200 }
201
207 void push_back(T&& value) {
208 if (m_size >= Capacity) {
209 throw std::out_of_range("StaticVector capacity exceeded");
210 }
211 new (data() + m_size) T(std::move(value));
212 ++m_size;
213 }
214
222 template <typename... Args>
223 T& emplace_back(Args&&... args) {
224 if (m_size >= Capacity) {
225 throw std::out_of_range("StaticVector capacity exceeded");
226 }
227 T* slot = new (data() + m_size) T(std::forward<Args>(args)...);
228 ++m_size;
229 return *slot;
230 }
231
237 void pop_back() noexcept {
238 if (m_size > 0) {
239 --m_size;
240 data()[m_size].~T();
241 }
242 }
243
252 void resize(size_type new_size) {
253 if (new_size > Capacity) {
254 throw std::out_of_range("StaticVector resize exceeds capacity");
255 }
256 while (m_size > new_size) {
257 pop_back();
258 }
259 while (m_size < new_size) {
260 emplace_back();
261 }
262 }
263
270 void resize(size_type new_size, const T& value) {
271 if (new_size > Capacity) {
272 throw std::out_of_range("StaticVector resize exceeds capacity");
273 }
274 while (m_size > new_size) {
275 pop_back();
276 }
277 while (m_size < new_size) {
278 push_back(value);
279 }
280 }
281
291 void reserve(size_type requested) {
292 if (requested > Capacity) {
293 throw std::out_of_range("StaticVector reserve exceeds capacity");
294 }
295 // No-op: storage is always pre-allocated
296 }
297
298private:
299 alignas(T) unsigned char m_storage[sizeof(T) * Capacity]{};
300 size_type m_size{0};
301};
302
303} // namespace bcnp
Fixed-capacity vector with no heap allocation.
StaticVector(const StaticVector &other)
Copy constructor - deep copies all elements.
const T & operator[](size_type index) const noexcept
Access element by index (no bounds checking).
const T & front() const noexcept
Access first element (undefined if empty).
void reserve(size_type requested)
Reserve capacity (no-op for StaticVector).
T & back() noexcept
Access last element (undefined if empty).
T & front() noexcept
Access first element (undefined if empty).
StaticVector() noexcept=default
Default constructor - creates empty vector.
void push_back(T &&value)
Add element by move.
void resize(size_type new_size)
Resize the vector.
T & operator[](size_type index) noexcept
Access element by index (no bounds checking).
void pop_back() noexcept
Remove last element.
T value_type
Element type.
iterator begin() noexcept
const T & back() const noexcept
Access last element (undefined if empty).
void push_back(const T &value)
Add element by copy.
const_iterator end() const noexcept
void resize(size_type new_size, const T &value)
Resize with fill value.
T & emplace_back(Args &&... args)
Construct element in-place at end.
T & at(size_type index)
Access element with bounds checking.
T * iterator
Mutable iterator type.
size_type size() const noexcept
Get current number of elements.
const_iterator cend() const noexcept
bool empty() const noexcept
Check if vector is empty.
const T * data() const noexcept
Get pointer to underlying storage.
StaticVector & operator=(const StaticVector &other)
Copy assignment operator.
StaticVector(StaticVector &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
Move constructor - moves all elements.
const_iterator begin() const noexcept
constexpr size_type capacity() const noexcept
Get maximum capacity (compile-time constant).
void clear() noexcept
Remove all elements.
iterator end() noexcept
StaticVector & operator=(StaticVector &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_destructible_v< T >)
Move assignment operator.
const T * const_iterator
Const iterator type.
T * data() noexcept
Get pointer to underlying storage.
std::size_t size_type
Size/index type.
const T & at(size_type index) const
Access element with bounds checking.
const_iterator cbegin() const noexcept
~StaticVector()
Destructor - properly destroys all elements.