8#ifndef SEN_CORE_BASE_STATIC_VECTOR_H
9#define SEN_CORE_BASE_STATIC_VECTOR_H
24#define SEN_VECTOR_CHECK(expr, type) \
25 ((expr) ? static_cast<void>(0) : ::sen::impl::senCheckImpl(false, ::sen::impl::CheckType::type, #expr, SEN_SL()))
34template <
typename T,
typename Range,
typename Index>
35inline T& index(Range&& range, Index&& i)
noexcept
38 SEN_VECTOR_CHECK(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)), expect);
42 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
46template <
typename T,
typename Range,
typename Index>
47inline const T& cindex(Range&& range, Index&& i)
noexcept
50 SEN_VECTOR_CHECK(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)), expect);
54 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
88 static constexpr bool nothrowDes = std::is_nothrow_destructible_v<T>;
144 return reinterpret_cast<pointer>(dataPtr_);
191 template <
class InputIt>
288 return impl::index<value_type>(*
this, 0U);
298 return impl::cindex<value_type>(*
this, 0U);
308 return impl::index<value_type>(*
this,
size() - 1);
318 return impl::cindex<value_type>(*
this,
size() - 1);
329 internalDestroyAll();
369 template <typename... Args>
384 template <typename... Args>
449 template <class InputIt>
463 template <class InputIt>
525 template <typename Iterator>
526 [[nodiscard]]
Maybe checkIteratorRange(Iterator itr) noexcept;
529 template <typename IteratorA, typename IteratorB>
530 [[nodiscard]]
Maybe checkIteratorPair(IteratorA first, IteratorB last) noexcept;
558 std::size_t capacity_;
560 std::size_t size_ = 0U;
576template <
typename T, std::
size_t s>
581 static_assert(
staticCapacity != 0U,
"Vectors of no capacity are not supported");
604 template <
class InputIt>
634 [[nodiscard]]
Base&
base() noexcept {
return *
this; }
637 [[nodiscard]]
const Base&
base() const noexcept {
return *
this; }
640 alignas(T) std::byte data_[
sizeof(T) * s];
652template <
typename T, std::
size_t size>
655 StaticVector<T, size> const& rhs)
noexcept(
noexcept(std::declval<T const&>() == std::declval<T const&>()))
657 if (lhs.size() != rhs.size())
662 return lhs.size() == 0 || std::equal(lhs.begin(), lhs.end(), rhs.begin(), std::equal_to<T> {});
668template <
typename T, std::
size_t size>
672 std::declval<StaticVector<T, size>
const&>()))
674 return !(lhs == rhs);
681template <
typename T, std::
size_t size>
682std::enable_if_t<HasOperator<T>::lt,
bool>
operator<(
const StaticVector<T, size>& lhs,
683 const StaticVector<T, size>& rhs)
684 noexcept(
noexcept(std::declval<const T&>() < std::declval<const T&>()))
686 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
695template <
typename T, std::
size_t size>
698 noexcept(
noexcept(std::declval<const T&>() < std::declval<const T&>()))
700 return std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(), lhs.end());
706template <
typename T, std::
size_t size>
721#define SEN_VECTOR_TRY(...) \
723 auto res = __VA_ARGS__; \
726 return Err(res.getError()); \
775template <
class InputIt>
780 if (last - first < 0)
822 static_assert(std::is_default_constructible<T>::value,
823 "this version of push_back requires a default constructible type");
833template <
typename... Args>
846 if (position ==
end())
848 std::ignore =
emplace_back(std::forward<Args>(args)...);
852 const auto previousEnd =
end();
857 if (std::distance(position, previousEnd) != 1)
860 std::move_backward(position,
end() - 2,
end() - 1);
863 std::destroy_at(position);
867 ::new (std::addressof(*position)) T(std::forward<Args>(args)...);
873template <
typename... Args>
882 new (
end()) T(std::forward<Args>(args)...);
899 auto ptr =
end() - 1;
900 std::destroy_at(ptr);
920template <
class InputIt>
935 const size_t insertN = std::distance(first, last);
936 const size_t insertBegin = std::distance(
begin(), position);
937 const size_t insertEnd = insertBegin + insertN;
941 size_t constructOldN;
947 const size_t tailN =
size() - insertBegin;
952 constructOldN = tailN;
953 pConstructOld =
begin() + insertEnd;
957 copyOldN = tailN - insertN;
958 constructOldN = insertN;
959 pConstructOld = pEnd;
962 const size_t copyNewN = constructOldN;
963 const size_t constructNewN = insertN - copyNewN;
967 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
971 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
975 std::uninitialized_copy(first + copyNewN, first + copyNewN + constructNewN, pEnd);
979 std::copy(first, first + copyNewN,
begin() + insertBegin);
997 if (position ==
end())
1007 std::move_backward(position,
end() - 2,
end() - 1);
1010 *position = std::move(x);
1013 return Ok(position);
1016template <
typename T>
1023 if (
const auto newSize =
size() + n; newSize >
capacity())
1030 return Ok(position);
1033 const size_t insertN = n;
1034 const size_t insertBegin = std::distance(
begin(), position);
1035 const size_t insertEnd = insertBegin + insertN;
1039 size_t constructOldN;
1045 const size_t tailN =
size() - insertBegin;
1047 if (insertN > tailN)
1050 constructOldN = tailN;
1051 pConstructOld =
begin() + insertEnd;
1055 copyOldN = tailN - insertN;
1056 constructOldN = insertN;
1057 pConstructOld = pEnd;
1060 size_t copyNewN = constructOldN;
1061 size_t constructNewN = insertN - copyNewN;
1065 std::uninitialized_move(
static_cast<iterator>(pEnd - constructOldN), pEnd, pConstructOld);
1069 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
1072 std::uninitialized_fill_n(pEnd, constructNewN, x);
1076 std::fill_n(
begin() + insertBegin, copyNewN, x);
1080 return Ok(position);
1083template <
typename T>
1089 return insert(position, list.begin(), list.end());
1092template <
typename T>
1093template <
class InputIt>
1106 const size_t insertN = std::distance(first, last);
1107 const size_t insertBegin = std::distance(
begin(), position);
1108 const size_t insertEnd = insertBegin + insertN;
1112 size_t constructOldN;
1117 const size_t tailN =
size() - insertBegin;
1119 if (insertN > tailN)
1122 constructOldN = tailN;
1123 pConstructOld =
begin() + insertEnd;
1127 moveOldN = tailN - insertN;
1128 constructOldN = insertN;
1129 pConstructOld = pEnd;
1132 const size_t copyNewN = constructOldN;
1133 const size_t constructNewN = insertN - copyNewN;
1137 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
1141 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + moveOldN,
begin() + insertEnd + moveOldN);
1145 std::uninitialized_move(first + copyNewN, first + copyNewN + constructNewN, pEnd);
1149 std::move(first, first + copyNewN,
begin() + insertBegin);
1153 return Ok(position);
1156template <
typename T>
1160 static_assert(std::is_nothrow_copy_constructible<T>::value,
"T is not supported");
1163 if (newSize ==
size())
1173 if (newSize >
size())
1184template <
typename T>
1189 if (newSize ==
size())
1199 if (newSize >
size())
1201 return emplaceMultiple(newSize -
size());
1208template <
typename T>
1216 std::move(position + 1,
end(), position);
1219 auto ptr =
end() - 1;
1220 std::destroy_at(ptr);
1222 return Ok(position);
1225template <
typename T>
1239 if (first ==
begin() && last ==
end())
1246 std::move(last,
end(), first);
1249 const auto nDelete = std::distance(first, last);
1250 std::destroy(
end() - nDelete,
end());
1258template <
typename T>
1262 const size_type newSize = size() + n;
1265 while (newSize != size())
1268 std::ignore = emplace_back();
1274template <
typename T>
1275template <
typename Iterator>
1278 if (itr >= begin() && itr <= end())
1286template <
typename T>
1287template <
typename IteratorA,
typename IteratorB>
1289 IteratorB last)
noexcept
1298template <
typename T>
1305template <
typename T>
1306template <
class InputIt>
1307inline void StaticVectorBase<T>::internalDestroy(InputIt first, InputIt last)
noexcept(
nothrowDes)
1314 for (; first != last; ++first)
1316 std::destroy_at(first);
1322template <
typename T, std::
size_t c>
1325 auto result = this->
resize(n);
1327 std::ignore = result;
1330template <
typename T, std::
size_t c>
1334 auto result = this->
resize(n, value);
1336 std::ignore = result;
1339template <
typename T, std::
size_t c>
1343 auto result = this->
assign(std::move(list));
1345 std::ignore = result;
1348template <
typename T, std::
size_t c>
1349template <
class InputIt>
1353 auto result = this->
assign(first, last);
1355 std::ignore = result;
1358template <
typename T, std::
size_t c>
1362 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1364 std::ignore = result;
1367template <
typename T, std::
size_t c>
1370 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1372 std::ignore = result;
1373 other.internalSetSize(0U);
1376template <
typename T, std::
size_t c>
1383 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1385 std::ignore = result;
1390template <
typename T, std::
size_t c>
1397 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1399 std::ignore = result;
1400 other.internalSetSize(0U);
1405template <
typename T, std::
size_t c>
1409 other = std::move(*
this);
1410 (*this) = std::move(tmp);
1415#undef SEN_VECTOR_TRY
1416#undef SEN_VECTOR_CHECK
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
Contiguous view of elements of type T. Inspired by http://www.open-std.org/jtc1/sc22/wg21/docs/papers...
Definition span.h:34
const_reverse_iterator rbegin() const noexcept
Reverse iterator to the first element. Complexity: constant.
Definition static_vector.h:223
pointer data() noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:142
virtual ~StaticVectorBase() noexcept
Definition static_vector.h:549
Result< void, StaticVectorError > Maybe
Definition static_vector.h:111
size_type maxSize() const noexcept
Max element count (same as capacity()). Complexity: constant.
Definition static_vector.h:131
static constexpr bool nothrowMoveCons
Definition static_vector.h:91
static constexpr bool nothrowDefaultConsAndDes
Definition static_vector.h:93
reverse_iterator rend() noexcept
Returns a reverse iterator to the element following the last element of the reversed vector....
Definition static_vector.h:229
pointer iterator
Definition static_vector.h:104
size_type capacity() const noexcept
Maximum number of elements that can be allocated in the storage. Complexity: constant.
Definition static_vector.h:127
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:203
static constexpr bool nothrowCopyCons
Definition static_vector.h:90
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:734
ptrdiff_t difference_type
Definition static_vector.h:98
void clear() noexcept(nothrowDes)
Clears the vector. This function destroys all the elements. Complexity: linear in size().
Definition static_vector.h:327
const_iterator cend() noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:249
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:761
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:295
const_pointer const_iterator
Definition static_vector.h:105
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:315
Maybe resize(size_type newSize, const Value &value) noexcept(nothrowCopyAndDes)
Definition static_vector.h:1157
reverse_iterator rbegin() noexcept
Reverse iterator to the first element. Complexity: constant.
Definition static_vector.h:219
void internalSetSize(std::size_t newSize) noexcept
Changes the container size to newSize.
Definition static_vector.h:1299
const_reference operator[](size_type i) const noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:278
MaybeIterator insert(iterator position, const_reference x) noexcept(nothrowCopyCons)
Definition static_vector.h:906
bool empty() const noexcept
true if the container is empty. Complexity: constant
Definition static_vector.h:149
static constexpr bool nothrowCopyAndDes
Definition static_vector.h:92
Maybe emplace_back(Args &&... args) noexcept(//NOLINT(readability-identifier-naming) nothrowMoveCons)
Definition static_vector.h:874
Maybe pop_back() noexcept(nothrowDes)
Definition static_vector.h:891
Result< iterator, StaticVectorError > MaybeIterator
Definition static_vector.h:112
const_iterator cend() const noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:253
StaticVectorBase(std::size_t capacity, void *dataPtr) noexcept
Definition static_vector.h:545
MaybeIterator emplace(iterator position, Args &&... args) noexcept(nothrowMoveCons)
Definition static_vector.h:834
std::reverse_iterator< iterator > reverse_iterator
Definition static_vector.h:107
MaybeIterator move_insert(iterator position, InputIt first, InputIt last) noexcept(nothrowMoveCons)
Definition static_vector.h:1095
const_iterator cbegin() noexcept
Returns a const iterator to the first element of the vector. If the vector is empty,...
Definition static_vector.h:240
T && rvalue_reference
Definition static_vector.h:103
T const & const_reference
Definition static_vector.h:102
MaybeIterator erase(iterator position) noexcept(nothrowDes)
Definition static_vector.h:1209
std::size_t size_type
Definition static_vector.h:106
Maybe push_back(const T &value) noexcept(nothrowCopyCons)
Appends a value to the end of the container. Complexity: constant.
Definition static_vector.h:808
StaticVectorBase(const StaticVectorBase &) noexcept=delete
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_vector.h:108
reference back() noexcept
The element at the end of the container. Calling back on an empty container is undefined....
Definition static_vector.h:305
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:245
iterator end() noexcept
Iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:207
reference front() noexcept
The element at the beginning of the container. Calling front on an empty container is undefined....
Definition static_vector.h:285
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:235
bool full() const noexcept
true if the container is full. Complexity: constant
Definition static_vector.h:153
Maybe push_back() noexcept(nothrowDefaultCons)
Appends a value (default constructed) to the end of the container. Complexity: constant.
Definition static_vector.h:820
T & reference
Definition static_vector.h:101
reference operator[](size_type i) noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:266
T const * const_pointer
Definition static_vector.h:100
const_iterator end() const noexcept
Iterator to the element following the last element. Complexity: constant. NOLINTNEXTLINE(cppcoreguide...
Definition static_vector.h:215
const_pointer data() const noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:135
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:198
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:776
T * pointer
Definition static_vector.h:99
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:797
static constexpr bool nothrowDes
Definition static_vector.h:88
static constexpr bool nothrowDefaultCons
Definition static_vector.h:89
Maybe assign(const std::initializer_list< T > &list) noexcept(nothrowCopyCons)
Initializer list assignment. Complexity: linear in list.size().
Definition static_vector.h:748
void internalDestroy(InputIt first, InputIt last) noexcept(nothrowDes)
Definition static_vector.h:1307
size_type size() const noexcept
Element count. Complexity: constant.
Definition static_vector.h:123
T value_type
Definition static_vector.h:97
Stack-based, exception-free and resizable vector with fixed-capacity.
Definition static_vector.h:578
Base & base() noexcept
This object, as its base class.
Definition static_vector.h:634
StaticVector & operator=(const StaticVector &other) noexcept(Base::nothrowCopyCons)
Copy assignment. Complexity: linear in other.size().
Definition static_vector.h:1377
~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:637
static constexpr std::size_t staticCapacity
Definition static_vector.h:580
void swap(StaticVector &other) noexcept
Definition static_vector.h:1406
StaticVector() noexcept
Creates an empty vector.
Definition static_vector.h:588
StaticVectorBase< T > Base
Definition static_vector.h:584
impl::Err< void > Err() noexcept
If E is void, use the void specialization of Err.
Definition result.h:442
impl::Ok< void > Ok() noexcept
If T is void, use the void specialization of Ok.
Definition result.h:437
std::enable_if_t< HasOperator< T >::lt, bool > operator<(const StaticVector< T, size > &lhs, const StaticVector< T, size > &rhs) noexcept(noexcept(std::declval< const T & >()< std::declval< const T & >()))
Lexicographically compares two StaticVector objects.
Definition static_vector.h:682
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:64
constexpr Span< const T > makeConstSpan(const T *ptr, std::size_t size) noexcept
Takes in a type that can be passed to a contiguous range and returns a Span. The element types will b...
Definition span.h:248
std::enable_if_t< HasOperator< T >::lt, bool > operator>(const StaticVector< T, size > &lhs, const StaticVector< T, size > &rhs) noexcept(noexcept(std::declval< const T & >()< std::declval< const T & >()))
Lexicographically compares two StaticVector objects.
Definition static_vector.h:696
@ empty
Invalid operation on an empty vector.
Definition static_vector.h:67
@ badRange
The range is invalid.
Definition static_vector.h:66
@ full
The vector cannot hold more elements.
Definition static_vector.h:65
#define SEN_VECTOR_TRY(...)
Definition static_vector.h:721
#define SEN_VECTOR_CHECK(expr, type)
Definition static_vector.h:24