8#ifndef SEN_CORE_BASE_STATIC_VECTOR_H
9#define SEN_CORE_BASE_STATIC_VECTOR_H
27template <
typename T,
typename Range,
typename Index>
28inline T& index(Range&& range, Index&& i)
noexcept
31 SEN_EXPECT(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)));
35 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
39template <
typename T,
typename Range,
typename Index>
40inline const T& cindex(Range&& range, Index&& i)
noexcept
43 SEN_EXPECT(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)));
47 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
81 static constexpr bool nothrowDes = std::is_nothrow_destructible_v<T>;
137 return reinterpret_cast<pointer>(dataPtr_);
184 template <
class InputIt>
281 return impl::index<value_type>(*
this, 0U);
291 return impl::cindex<value_type>(*
this, 0U);
301 return impl::index<value_type>(*
this,
size() - 1);
311 return impl::cindex<value_type>(*
this,
size() - 1);
322 internalDestroyAll();
362 template <typename... Args>
377 template <typename... Args>
442 template <class InputIt>
456 template <class InputIt>
518 template <typename Iterator>
519 [[nodiscard]]
Maybe checkIteratorRange(Iterator itr) noexcept;
522 template <typename IteratorA, typename IteratorB>
523 [[nodiscard]]
Maybe checkIteratorPair(IteratorA first, IteratorB last) noexcept;
551 std::size_t capacity_;
553 std::size_t size_ = 0U;
569template <
typename T, std::
size_t s>
574 static_assert(
staticCapacity != 0U,
"Vectors of no capacity are not supported");
597 template <
class InputIt>
627 [[nodiscard]]
Base&
base() noexcept {
return *
this; }
630 [[nodiscard]]
const Base&
base() const noexcept {
return *
this; }
633 alignas(T) std::byte data_[
sizeof(T) * s];
642template <
typename T, std::
size_t size>
646 if (lhs.size() != rhs.size())
651 return lhs.size() == 0 || std::equal(lhs.begin(), lhs.end(), rhs.begin(), std::equal_to<T> {});
655template <
typename T, std::
size_t size>
659 return !(lhs == rhs);
671#define SEN_VECTOR_TRY(...) \
673 auto res = __VA_ARGS__; \
676 return Err(res.getError()); \
725template <
class InputIt>
730 if (last - first < 0)
772 static_assert(std::is_default_constructible<T>::value,
773 "this version of push_back requires a default constructible type");
783template <
typename... Args>
796 if (position ==
end())
798 std::ignore =
emplace_back(std::forward<Args...>(args...));
802 const auto previousEnd =
end();
807 if (std::distance(position, previousEnd) != 1)
810 std::move_backward(position,
end() - 2,
end() - 1);
813 std::destroy_at(position);
817 ::new (std::addressof(*position)) T(std::forward<Args>(args)...);
823template <
typename... Args>
832 new (
end()) T(std::forward<Args>(args)...);
849 auto ptr =
end() - 1;
850 std::destroy_at(ptr);
870template <
class InputIt>
885 const size_t insertN = std::distance(first, last);
886 const size_t insertBegin = std::distance(
begin(), position);
887 const size_t insertEnd = insertBegin + insertN;
891 size_t constructOldN;
896 if (insertEnd >
size())
899 constructOldN =
size() - insertBegin;
900 pConstructOld =
begin() + insertEnd;
904 copyOldN =
size() - insertBegin - insertN;
905 constructOldN = insertN;
906 pConstructOld = pEnd;
909 const size_t copyNewN = constructOldN;
910 const size_t constructNewN = insertN - copyNewN;
914 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
918 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
922 std::uninitialized_copy(first + copyNewN, first + copyNewN + constructNewN, pEnd);
926 std::copy(first, first + copyNewN,
begin() + insertBegin);
944 if (position ==
end())
954 std::move_backward(position,
end() - 2,
end() - 1);
957 *position = std::move(x);
970 if (
const auto newSize =
size() + n; newSize >
capacity())
980 const size_t insertN = n;
981 const size_t insertBegin = std::distance(
begin(), position);
982 const size_t insertEnd = insertBegin + insertN;
986 size_t constructOldN;
991 if (insertEnd >
size())
994 constructOldN =
size() - insertBegin;
995 pConstructOld =
begin() + insertEnd;
999 copyOldN =
size() - insertBegin - insertN;
1000 constructOldN = insertN;
1001 pConstructOld = pEnd;
1004 size_t copyNewN = constructOldN;
1005 size_t constructNewN = insertN - copyNewN;
1009 std::uninitialized_move(
static_cast<iterator>(pEnd - constructOldN), pEnd, pConstructOld);
1013 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
1016 std::uninitialized_fill_n(pEnd, constructNewN, x);
1020 std::fill_n(
begin() + insertBegin, copyNewN, x);
1024 return Ok(position);
1027template <
typename T>
1033 return insert(position, list.begin(), list.end());
1036template <
typename T>
1037template <
class InputIt>
1050 const size_t insertN = std::distance(first, last);
1051 const size_t insertBegin = std::distance(
begin(), position);
1052 const size_t insertEnd = insertBegin + insertN;
1056 size_t constructOldN;
1060 if (insertEnd >
size())
1063 constructOldN =
size() - insertBegin;
1064 pConstructOld =
begin() + insertEnd;
1068 moveOldN =
size() - insertBegin - insertN;
1069 constructOldN = insertN;
1070 pConstructOld = pEnd;
1073 const size_t copyNewN = constructOldN;
1074 const size_t constructNewN = insertN - copyNewN;
1078 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
1082 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + moveOldN,
begin() + insertEnd + moveOldN);
1086 std::uninitialized_move(first + copyNewN, first + copyNewN + constructNewN, pEnd);
1090 std::move(first, first + copyNewN,
begin() + insertBegin);
1094 return Ok(position);
1097template <
typename T>
1101 static_assert(std::is_nothrow_copy_constructible<T>::value,
"T is not supported");
1104 if (newSize ==
size())
1114 if (newSize >
size())
1125template <
typename T>
1130 if (newSize ==
size())
1140 if (newSize >
size())
1142 return emplaceMultiple(newSize -
size());
1149template <
typename T>
1157 std::move(position + 1,
end(), position);
1160 auto ptr =
end() - 1;
1161 std::destroy_at(ptr);
1163 return Ok(position);
1166template <
typename T>
1176 if (first ==
begin() && last ==
end())
1187 std::move(last,
end(), first);
1190 const auto nDelete = std::distance(first, last);
1191 std::destroy(
end() - nDelete,
end());
1199template <
typename T>
1203 const size_type newSize = size() + n;
1206 while (newSize != size())
1209 std::ignore = emplace_back();
1215template <
typename T>
1216template <
typename Iterator>
1219 if (itr >= begin() && itr <= end())
1227template <
typename T>
1228template <
typename IteratorA,
typename IteratorB>
1230 IteratorB last)
noexcept
1239template <
typename T>
1246template <
typename T>
1247template <
class InputIt>
1248inline void StaticVectorBase<T>::internalDestroy(InputIt first, InputIt last)
noexcept(
nothrowDes)
1255 for (; first != last; ++first)
1257 std::destroy_at(first);
1263template <
typename T, std::
size_t c>
1266 auto result = this->
resize(n);
1268 std::ignore = result;
1271template <
typename T, std::
size_t c>
1275 auto result = this->
resize(n, value);
1277 std::ignore = result;
1280template <
typename T, std::
size_t c>
1284 auto result = this->
assign(std::move(list));
1286 std::ignore = result;
1289template <
typename T, std::
size_t c>
1290template <
class InputIt>
1294 auto result = this->
assign(first, last);
1296 std::ignore = result;
1299template <
typename T, std::
size_t c>
1303 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1305 std::ignore = result;
1308template <
typename T, std::
size_t c>
1311 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1313 std::ignore = result;
1314 other.internalSetSize(0U);
1317template <
typename T, std::
size_t c>
1324 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1326 std::ignore = result;
1331template <
typename T, std::
size_t c>
1338 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1340 std::ignore = result;
1341 other.internalSetSize(0U);
1346template <
typename T, std::
size_t c>
1350 other = std::move(*
this);
1351 (*this) = std::move(tmp);
1356#undef SEN_VECTOR_TRY
The following macros implement a replacement of assert that is connected to the overall fault handlin...
Result<T, E> is a template type that can be used to return and propagate errors. The intent is to rep...
Definition result.h:135
const_reverse_iterator rbegin() const noexcept
Reverse iterator to the first element. Complexity: constant.
Definition static_vector.h:216
pointer data() noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:135
virtual ~StaticVectorBase() noexcept
Definition static_vector.h:542
Result< void, StaticVectorError > Maybe
Definition static_vector.h:104
size_type maxSize() const noexcept
Max element count (same as capacity()). Complexity: constant.
Definition static_vector.h:124
static constexpr bool nothrowMoveCons
Definition static_vector.h:84
static constexpr bool nothrowDefaultConsAndDes
Definition static_vector.h:86
reverse_iterator rend() noexcept
Returns a reverse iterator to the element following the last element of the reversed vector....
Definition static_vector.h:222
pointer iterator
Definition static_vector.h:97
size_type capacity() const noexcept
Maximum number of elements that can be allocated in the storage. Complexity: constant.
Definition static_vector.h:120
const_iterator begin() const noexcept
Returns an iterator to the first element of the vector. If the vector is empty, the returned iterator...
Definition static_vector.h:196
static constexpr bool nothrowCopyCons
Definition static_vector.h:83
Maybe assign(size_type n, const T &u) noexcept(nothrowCopyCons)
Clears the vector and assigns n copies of u to it. Complexity: linear in n.
Definition static_vector.h:684
ptrdiff_t difference_type
Definition static_vector.h:91
void clear() noexcept(nothrowDes)
Clears the vector. This function destroys all the elements. Complexity: linear in size().
Definition static_vector.h:320
const_iterator cend() noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:242
StaticVectorBase(StaticVectorBase &&) noexcept=delete
Maybe assign(std::initializer_list< T > &&list) noexcept(nothrowMoveCons)
Initializer list assignment (r-value version). Complexity: linear in list.size().
Definition static_vector.h:711
const_reference front() const noexcept
The element at the beginning of the container (const version). Calling front on an empty container is...
Definition static_vector.h:288
const_pointer const_iterator
Definition static_vector.h:98
const_reference back() const noexcept
The element at the end of the container (const version). Calling back on an empty container is undefi...
Definition static_vector.h:308
Maybe resize(size_type newSize, const Value &value) noexcept(nothrowCopyAndDes)
Definition static_vector.h:1098
reverse_iterator rbegin() noexcept
Reverse iterator to the first element. Complexity: constant.
Definition static_vector.h:212
void internalSetSize(std::size_t newSize) noexcept
Changes the container size to newSize.
Definition static_vector.h:1240
const_reference operator[](size_type i) const noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:271
MaybeIterator insert(iterator position, const_reference x) noexcept(nothrowCopyCons)
Definition static_vector.h:856
bool empty() const noexcept
true if the container is empty. Complexity: constant
Definition static_vector.h:142
static constexpr bool nothrowCopyAndDes
Definition static_vector.h:85
Maybe emplace_back(Args &&... args) noexcept(//NOLINT(readability-identifier-naming) nothrowMoveCons)
Definition static_vector.h:824
Maybe pop_back() noexcept(nothrowDes)
Definition static_vector.h:841
Result< iterator, StaticVectorError > MaybeIterator
Definition static_vector.h:105
const_iterator cend() const noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:246
StaticVectorBase(std::size_t capacity, void *dataPtr) noexcept
Definition static_vector.h:538
MaybeIterator emplace(iterator position, Args &&... args) noexcept(nothrowMoveCons)
Definition static_vector.h:784
std::reverse_iterator< iterator > reverse_iterator
Definition static_vector.h:100
MaybeIterator move_insert(iterator position, InputIt first, InputIt last) noexcept(nothrowMoveCons)
Definition static_vector.h:1039
const_iterator cbegin() noexcept
Returns a const iterator to the first element of the vector. If the vector is empty,...
Definition static_vector.h:233
T && rvalue_reference
Definition static_vector.h:96
T const & const_reference
Definition static_vector.h:95
MaybeIterator erase(iterator position) noexcept(nothrowDes)
Definition static_vector.h:1150
std::size_t size_type
Definition static_vector.h:99
Maybe push_back(const T &value) noexcept(nothrowCopyCons)
Appends a value to the end of the container. Complexity: constant.
Definition static_vector.h:758
StaticVectorBase(const StaticVectorBase &) noexcept=delete
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_vector.h:101
reference back() noexcept
The element at the end of the container. Calling back on an empty container is undefined....
Definition static_vector.h:298
const_iterator cbegin() const noexcept
Returns a const iterator to the first element of the vector. If the vector is empty,...
Definition static_vector.h:238
iterator end() noexcept
Iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:200
reference front() noexcept
The element at the beginning of the container. Calling front on an empty container is undefined....
Definition static_vector.h:278
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the element following the last element of the reversed vector....
Definition static_vector.h:228
bool full() const noexcept
true if the container is full. Complexity: constant
Definition static_vector.h:146
Maybe push_back() noexcept(nothrowDefaultCons)
Appends a value (default constructed) to the end of the container. Complexity: constant.
Definition static_vector.h:770
T & reference
Definition static_vector.h:94
reference operator[](size_type i) noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:259
T const * const_pointer
Definition static_vector.h:93
const_iterator end() const noexcept
Iterator to the element following the last element. Complexity: constant. NOLINTNEXTLINE(cppcoreguide...
Definition static_vector.h:208
const_pointer data() const noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:128
iterator begin() noexcept
Returns an iterator to the first element of the vector. If the vector is empty, the returned iterator...
Definition static_vector.h:191
Maybe assign(InputIt first, InputIt last) noexcept(nothrowCopyCons)
Clears the vector and assigns a range to it. Complexity: linear in distance(first,...
Definition static_vector.h:726
T * pointer
Definition static_vector.h:92
Maybe push_back(T &&value) noexcept(nothrowMoveCons)
Appends a value to the end of the container (r-value version). Complexity: constant.
Definition static_vector.h:747
static constexpr bool nothrowDes
Definition static_vector.h:81
static constexpr bool nothrowDefaultCons
Definition static_vector.h:82
Maybe assign(const std::initializer_list< T > &list) noexcept(nothrowCopyCons)
Initializer list assignment. Complexity: linear in list.size().
Definition static_vector.h:698
void internalDestroy(InputIt first, InputIt last) noexcept(nothrowDes)
Definition static_vector.h:1248
size_type size() const noexcept
Element count. Complexity: constant.
Definition static_vector.h:116
T value_type
Definition static_vector.h:90
Stack-based, exception-free and resizable vector with fixed-capacity.
Definition static_vector.h:571
Base & base() noexcept
This object, as its base class.
Definition static_vector.h:627
StaticVector & operator=(const StaticVector &other) noexcept(Base::nothrowCopyCons)
Copy assignment. Complexity: linear in other.size().
Definition static_vector.h:1318
~StaticVector() noexcept override=default
Deletes all internal elements. Complexity: linear in size().
const Base & base() const noexcept
This object, as its base class.
Definition static_vector.h:630
static constexpr std::size_t staticCapacity
Definition static_vector.h:573
void swap(StaticVector &other) noexcept
Definition static_vector.h:1347
StaticVector() noexcept
Creates an empty vector.
Definition static_vector.h:581
StaticVectorBase< T > Base
Definition static_vector.h:577
impl::Err< void > Err() noexcept
If E is void, use the void specialization of Err.
Definition result.h:439
impl::Ok< void > Ok() noexcept
If T is void, use the void specialization of Ok.
Definition result.h:434
#define SEN_ASSERT(expr)
Checks an intermediate result produced by a procedure (not an input or output). NOLINTNEXTLINE.
Definition assert.h:39
#define SEN_EXPECT(expr)
Checks a pre-condition of a procedure (function parameter for example). NOLINTNEXTLINE.
Definition assert.h:36
constexpr bool operator!=(const Span< T > &lhs, const Span< T > &rhs) noexcept
Definition span.h:190
constexpr bool operator==(const Span< T > &lhs, const Span< T > &rhs) noexcept
Definition span.h:184
StaticVectorError
Things that can go wrong when using a StaticVector.
Definition static_vector.h:57
@ empty
Invalid operation on an empty vector.
Definition static_vector.h:60
@ badRange
The range is invalid.
Definition static_vector.h:59
@ full
The vector cannot hold more elements.
Definition static_vector.h:58
#define SEN_VECTOR_TRY(...)
Definition static_vector.h:671