8#ifndef SEN_CORE_BASE_STATIC_VECTOR_H
9#define SEN_CORE_BASE_STATIC_VECTOR_H
30template <
typename T,
typename Range,
typename Index>
31inline T& index(Range&& range, Index&& i)
noexcept
34 SEN_EXPECT(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)));
38 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
42template <
typename T,
typename Range,
typename Index>
43inline const T& cindex(Range&& range, Index&& i)
noexcept
46 SEN_EXPECT(
static_cast<ptrdiff_t
>(i) < (std::end(range) - std::begin(range)));
50 return std::begin(std::forward<Range>(range))[std::forward<Index>(i)];
84 static constexpr bool nothrowDes = std::is_nothrow_destructible_v<T>;
140 return reinterpret_cast<pointer>(dataPtr_);
187 template <
class InputIt>
284 return impl::index<value_type>(*
this, 0U);
294 return impl::cindex<value_type>(*
this, 0U);
304 return impl::index<value_type>(*
this,
size() - 1);
314 return impl::cindex<value_type>(*
this,
size() - 1);
325 internalDestroyAll();
365 template <typename... Args>
380 template <typename... Args>
445 template <class InputIt>
459 template <class InputIt>
521 template <typename Iterator>
522 [[nodiscard]]
Maybe checkIteratorRange(Iterator itr) noexcept;
525 template <typename IteratorA, typename IteratorB>
526 [[nodiscard]]
Maybe checkIteratorPair(IteratorA first, IteratorB last) noexcept;
554 std::size_t capacity_;
556 std::size_t size_ = 0U;
572template <
typename T, std::
size_t s>
577 static_assert(
staticCapacity != 0U,
"Vectors of no capacity are not supported");
600 template <
class InputIt>
630 [[nodiscard]]
Base&
base() noexcept {
return *
this; }
633 [[nodiscard]]
const Base&
base() const noexcept {
return *
this; }
636 alignas(T) std::byte data_[
sizeof(T) * s];
648template <
typename T, std::
size_t size>
651 StaticVector<T, size> const& rhs)
noexcept(
noexcept(std::declval<T const&>() == std::declval<T const&>()))
653 if (lhs.size() != rhs.size())
658 return lhs.size() == 0 || std::equal(lhs.begin(), lhs.end(), rhs.begin(), std::equal_to<T> {});
664template <
typename T, std::
size_t size>
668 std::declval<StaticVector<T, size>
const&>()))
670 return !(lhs == rhs);
677template <
typename T, std::
size_t size>
678std::enable_if_t<HasOperator<T>::lt,
bool>
operator<(
const StaticVector<T, size>& lhs,
679 const StaticVector<T, size>& rhs)
680 noexcept(
noexcept(std::declval<const T&>() < std::declval<const T&>()))
682 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
691template <
typename T, std::
size_t size>
694 noexcept(
noexcept(std::declval<const T&>() < std::declval<const T&>()))
696 return std::lexicographical_compare(rhs.begin(), rhs.end(), lhs.begin(), lhs.end());
702template <
typename T, std::
size_t size>
717#define SEN_VECTOR_TRY(...) \
719 auto res = __VA_ARGS__; \
722 return Err(res.getError()); \
771template <
class InputIt>
776 if (last - first < 0)
818 static_assert(std::is_default_constructible<T>::value,
819 "this version of push_back requires a default constructible type");
829template <
typename... Args>
842 if (position ==
end())
844 std::ignore =
emplace_back(std::forward<Args>(args)...);
848 const auto previousEnd =
end();
853 if (std::distance(position, previousEnd) != 1)
856 std::move_backward(position,
end() - 2,
end() - 1);
859 std::destroy_at(position);
863 ::new (std::addressof(*position)) T(std::forward<Args>(args)...);
869template <
typename... Args>
878 new (
end()) T(std::forward<Args>(args)...);
895 auto ptr =
end() - 1;
896 std::destroy_at(ptr);
916template <
class InputIt>
931 const size_t insertN = std::distance(first, last);
932 const size_t insertBegin = std::distance(
begin(), position);
933 const size_t insertEnd = insertBegin + insertN;
937 size_t constructOldN;
942 if (insertEnd >
size())
945 constructOldN =
size() - insertBegin;
946 pConstructOld =
begin() + insertEnd;
950 copyOldN =
size() - insertBegin - insertN;
951 constructOldN = insertN;
952 pConstructOld = pEnd;
955 const size_t copyNewN = constructOldN;
956 const size_t constructNewN = insertN - copyNewN;
960 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
964 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
968 std::uninitialized_copy(first + copyNewN, first + copyNewN + constructNewN, pEnd);
972 std::copy(first, first + copyNewN,
begin() + insertBegin);
990 if (position ==
end())
1000 std::move_backward(position,
end() - 2,
end() - 1);
1003 *position = std::move(x);
1006 return Ok(position);
1009template <
typename T>
1016 if (
const auto newSize =
size() + n; newSize >
capacity())
1023 return Ok(position);
1026 const size_t insertN = n;
1027 const size_t insertBegin = std::distance(
begin(), position);
1028 const size_t insertEnd = insertBegin + insertN;
1032 size_t constructOldN;
1037 if (insertEnd >
size())
1040 constructOldN =
size() - insertBegin;
1041 pConstructOld =
begin() + insertEnd;
1045 copyOldN =
size() - insertBegin - insertN;
1046 constructOldN = insertN;
1047 pConstructOld = pEnd;
1050 size_t copyNewN = constructOldN;
1051 size_t constructNewN = insertN - copyNewN;
1055 std::uninitialized_move(
static_cast<iterator>(pEnd - constructOldN), pEnd, pConstructOld);
1059 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + copyOldN,
begin() + insertEnd + copyOldN);
1062 std::uninitialized_fill_n(pEnd, constructNewN, x);
1066 std::fill_n(
begin() + insertBegin, copyNewN, x);
1070 return Ok(position);
1073template <
typename T>
1079 return insert(position, list.begin(), list.end());
1082template <
typename T>
1083template <
class InputIt>
1096 const size_t insertN = std::distance(first, last);
1097 const size_t insertBegin = std::distance(
begin(), position);
1098 const size_t insertEnd = insertBegin + insertN;
1102 size_t constructOldN;
1106 if (insertEnd >
size())
1109 constructOldN =
size() - insertBegin;
1110 pConstructOld =
begin() + insertEnd;
1114 moveOldN =
size() - insertBegin - insertN;
1115 constructOldN = insertN;
1116 pConstructOld = pEnd;
1119 const size_t copyNewN = constructOldN;
1120 const size_t constructNewN = insertN - copyNewN;
1124 std::uninitialized_move(pEnd - constructOldN, pEnd, pConstructOld);
1128 std::move_backward(
begin() + insertBegin,
begin() + insertBegin + moveOldN,
begin() + insertEnd + moveOldN);
1132 std::uninitialized_move(first + copyNewN, first + copyNewN + constructNewN, pEnd);
1136 std::move(first, first + copyNewN,
begin() + insertBegin);
1140 return Ok(position);
1143template <
typename T>
1147 static_assert(std::is_nothrow_copy_constructible<T>::value,
"T is not supported");
1150 if (newSize ==
size())
1160 if (newSize >
size())
1171template <
typename T>
1176 if (newSize ==
size())
1186 if (newSize >
size())
1188 return emplaceMultiple(newSize -
size());
1195template <
typename T>
1203 std::move(position + 1,
end(), position);
1206 auto ptr =
end() - 1;
1207 std::destroy_at(ptr);
1209 return Ok(position);
1212template <
typename T>
1226 if (first ==
begin() && last ==
end())
1233 std::move(last,
end(), first);
1236 const auto nDelete = std::distance(first, last);
1237 std::destroy(
end() - nDelete,
end());
1245template <
typename T>
1249 const size_type newSize = size() + n;
1252 while (newSize != size())
1255 std::ignore = emplace_back();
1261template <
typename T>
1262template <
typename Iterator>
1265 if (itr >= begin() && itr <= end())
1273template <
typename T>
1274template <
typename IteratorA,
typename IteratorB>
1276 IteratorB last)
noexcept
1285template <
typename T>
1292template <
typename T>
1293template <
class InputIt>
1294inline void StaticVectorBase<T>::internalDestroy(InputIt first, InputIt last)
noexcept(
nothrowDes)
1301 for (; first != last; ++first)
1303 std::destroy_at(first);
1309template <
typename T, std::
size_t c>
1312 auto result = this->
resize(n);
1314 std::ignore = result;
1317template <
typename T, std::
size_t c>
1321 auto result = this->
resize(n, value);
1323 std::ignore = result;
1326template <
typename T, std::
size_t c>
1330 auto result = this->
assign(std::move(list));
1332 std::ignore = result;
1335template <
typename T, std::
size_t c>
1336template <
class InputIt>
1340 auto result = this->
assign(first, last);
1342 std::ignore = result;
1345template <
typename T, std::
size_t c>
1349 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1351 std::ignore = result;
1354template <
typename T, std::
size_t c>
1357 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1359 std::ignore = result;
1360 other.internalSetSize(0U);
1363template <
typename T, std::
size_t c>
1370 auto result = this->
insert(this->
begin(), other.begin(), other.end());
1372 std::ignore = result;
1377template <
typename T, std::
size_t c>
1384 auto result = this->
move_insert(this->
begin(), other.begin(), other.end());
1386 std::ignore = result;
1387 other.internalSetSize(0U);
1392template <
typename T, std::
size_t c>
1396 other = std::move(*
this);
1397 (*this) = std::move(tmp);
1402#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
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:219
pointer data() noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:138
virtual ~StaticVectorBase() noexcept
Definition static_vector.h:545
Result< void, StaticVectorError > Maybe
Definition static_vector.h:107
size_type maxSize() const noexcept
Max element count (same as capacity()). Complexity: constant.
Definition static_vector.h:127
static constexpr bool nothrowMoveCons
Definition static_vector.h:87
static constexpr bool nothrowDefaultConsAndDes
Definition static_vector.h:89
reverse_iterator rend() noexcept
Returns a reverse iterator to the element following the last element of the reversed vector....
Definition static_vector.h:225
pointer iterator
Definition static_vector.h:100
size_type capacity() const noexcept
Maximum number of elements that can be allocated in the storage. Complexity: constant.
Definition static_vector.h:123
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:199
static constexpr bool nothrowCopyCons
Definition static_vector.h:86
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:730
ptrdiff_t difference_type
Definition static_vector.h:94
void clear() noexcept(nothrowDes)
Clears the vector. This function destroys all the elements. Complexity: linear in size().
Definition static_vector.h:323
const_iterator cend() noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:245
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:757
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:291
const_pointer const_iterator
Definition static_vector.h:101
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:311
Maybe resize(size_type newSize, const Value &value) noexcept(nothrowCopyAndDes)
Definition static_vector.h:1144
reverse_iterator rbegin() noexcept
Reverse iterator to the first element. Complexity: constant.
Definition static_vector.h:215
void internalSetSize(std::size_t newSize) noexcept
Changes the container size to newSize.
Definition static_vector.h:1286
const_reference operator[](size_type i) const noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:274
MaybeIterator insert(iterator position, const_reference x) noexcept(nothrowCopyCons)
Definition static_vector.h:902
bool empty() const noexcept
true if the container is empty. Complexity: constant
Definition static_vector.h:145
static constexpr bool nothrowCopyAndDes
Definition static_vector.h:88
Maybe emplace_back(Args &&... args) noexcept(//NOLINT(readability-identifier-naming) nothrowMoveCons)
Definition static_vector.h:870
Maybe pop_back() noexcept(nothrowDes)
Definition static_vector.h:887
Result< iterator, StaticVectorError > MaybeIterator
Definition static_vector.h:108
const_iterator cend() const noexcept
Constant iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:249
StaticVectorBase(std::size_t capacity, void *dataPtr) noexcept
Definition static_vector.h:541
MaybeIterator emplace(iterator position, Args &&... args) noexcept(nothrowMoveCons)
Definition static_vector.h:830
std::reverse_iterator< iterator > reverse_iterator
Definition static_vector.h:103
MaybeIterator move_insert(iterator position, InputIt first, InputIt last) noexcept(nothrowMoveCons)
Definition static_vector.h:1085
const_iterator cbegin() noexcept
Returns a const iterator to the first element of the vector. If the vector is empty,...
Definition static_vector.h:236
T && rvalue_reference
Definition static_vector.h:99
T const & const_reference
Definition static_vector.h:98
MaybeIterator erase(iterator position) noexcept(nothrowDes)
Definition static_vector.h:1196
std::size_t size_type
Definition static_vector.h:102
Maybe push_back(const T &value) noexcept(nothrowCopyCons)
Appends a value to the end of the container. Complexity: constant.
Definition static_vector.h:804
StaticVectorBase(const StaticVectorBase &) noexcept=delete
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition static_vector.h:104
reference back() noexcept
The element at the end of the container. Calling back on an empty container is undefined....
Definition static_vector.h:301
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:241
iterator end() noexcept
Iterator to the element following the last element. Complexity: constant.
Definition static_vector.h:203
reference front() noexcept
The element at the beginning of the container. Calling front on an empty container is undefined....
Definition static_vector.h:281
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:231
bool full() const noexcept
true if the container is full. Complexity: constant
Definition static_vector.h:149
Maybe push_back() noexcept(nothrowDefaultCons)
Appends a value (default constructed) to the end of the container. Complexity: constant.
Definition static_vector.h:816
T & reference
Definition static_vector.h:97
reference operator[](size_type i) noexcept
Gets the element at index i. Complexity: constant.
Definition static_vector.h:262
T const * const_pointer
Definition static_vector.h:96
const_iterator end() const noexcept
Iterator to the element following the last element. Complexity: constant. NOLINTNEXTLINE(cppcoreguide...
Definition static_vector.h:211
const_pointer data() const noexcept
Direct access to the underlying storage. Complexity: constant.
Definition static_vector.h:131
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:194
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:772
T * pointer
Definition static_vector.h:95
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:793
static constexpr bool nothrowDes
Definition static_vector.h:84
static constexpr bool nothrowDefaultCons
Definition static_vector.h:85
Maybe assign(const std::initializer_list< T > &list) noexcept(nothrowCopyCons)
Initializer list assignment. Complexity: linear in list.size().
Definition static_vector.h:744
void internalDestroy(InputIt first, InputIt last) noexcept(nothrowDes)
Definition static_vector.h:1294
size_type size() const noexcept
Element count. Complexity: constant.
Definition static_vector.h:119
T value_type
Definition static_vector.h:93
Stack-based, exception-free and resizable vector with fixed-capacity.
Definition static_vector.h:574
Base & base() noexcept
This object, as its base class.
Definition static_vector.h:630
StaticVector & operator=(const StaticVector &other) noexcept(Base::nothrowCopyCons)
Copy assignment. Complexity: linear in other.size().
Definition static_vector.h:1364
~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:633
static constexpr std::size_t staticCapacity
Definition static_vector.h:576
void swap(StaticVector &other) noexcept
Definition static_vector.h:1393
StaticVector() noexcept
Creates an empty vector.
Definition static_vector.h:584
StaticVectorBase< T > Base
Definition static_vector.h:580
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
#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
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:678
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:60
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:692
@ empty
Invalid operation on an empty vector.
Definition static_vector.h:63
@ badRange
The range is invalid.
Definition static_vector.h:62
@ full
The vector cannot hold more elements.
Definition static_vector.h:61
#define SEN_VECTOR_TRY(...)
Definition static_vector.h:717