libcaramel
dynamic_array.hpp
Go to the documentation of this file.
1 
7 #pragma once
8 
9 #include <libcaramel/iterators/random_iterator.hpp>
10 #include <libcaramel/memory/memory_allocator.hpp>
11 #include <libcaramel/util/types.hpp>
12 
13 #include <gsl/gsl_assert>
14 
15 #include <concepts>
16 #include <cstdint>
17 #include <initializer_list>
18 #include <limits>
19 #include <memory>
20 #include <type_traits>
21 
22 namespace caramel::detail
23 {
24  template <typename First, typename Second>
25  auto synth_three_way(const First& lhs, const Second& rhs)
26  {
27  if constexpr (std::three_way_comparable_with<First, Second>)
28  {
29  return lhs <=> rhs;
30  }
31  else
32  {
33  if (lhs == rhs)
34  {
35  return std::strong_ordering::equal;
36  }
37 
38  if (lhs < rhs)
39  {
40  return std::strong_ordering::less;
41  }
42 
43  return std::strong_ordering::greater;
44  }
45  }
46 } // namespace caramel::detail
47 
48 namespace caramel
49 {
50  struct in_place_t
51  {
52  explicit constexpr in_place_t() = default;
53  };
54 
55  inline constexpr in_place_t in_place;
56 
68  template <typename Any, i64_t Size, typename Allocator = memory_allocator<Any>>
70  {
71  public:
72  using value_type = Any;
73  using size_type = std::int64_t;
74  using difference_type = std::ptrdiff_t;
75  using allocator_type = Allocator;
76  using reference = value_type&;
77  using const_reference = const value_type&;
78  using pointer = typename Allocator::pointer;
79  using const_pointer = typename Allocator::const_pointer;
82  using reverse_iterator = std::reverse_iterator<iterator>;
83  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
84 
85  public:
89  constexpr basic_dynamic_array() noexcept = default;
95  constexpr basic_dynamic_array(const allocator_type& allocator) : m_allocator{allocator} {}
105  constexpr basic_dynamic_array(size_type count, const_reference value,
106  const allocator_type& allocator = allocator_type{}) :
107  m_allocator{allocator}
108  {
109  Expects(count >= 0);
110 
111  assign(count, value);
112  }
119  constexpr basic_dynamic_array(std::initializer_list<Any> init,
120  const allocator_type& allocator = allocator_type{}) :
121  m_allocator{allocator}
122  {
123  assign(init);
124  }
132  template <std::input_iterator InputIt>
133  constexpr basic_dynamic_array(InputIt first, InputIt last,
134  const allocator_type& allocator = allocator_type{}) :
135  m_allocator{allocator}
136  {
137  assign(first, last);
138  }
145  constexpr basic_dynamic_array(const basic_dynamic_array& other)
146  {
147  if (this != &other)
148  {
149  *this = other;
150  }
151  }
160  constexpr basic_dynamic_array(const basic_dynamic_array& other,
161  const allocator_type& allocator)
162  {
163  if (this != &other)
164  {
165  clear();
166 
167  if (!is_static())
168  {
169  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
170  }
171 
172  reset_to_static();
173 
174  m_allocator = allocator;
175 
176  const size_type new_count = std::distance(std::begin(other), std::end(other));
177  if (new_count > capacity())
178  {
179  grow(new_count);
180  }
181 
182  m_size = new_count;
183 
184  std::uninitialized_copy(std::begin(other), std::end(other), begin());
185  }
186  }
194  constexpr basic_dynamic_array(basic_dynamic_array&& other) noexcept
195  {
196  if (!other.empty())
197  {
198  *this = std::move(other);
199  }
200  }
209  constexpr basic_dynamic_array(basic_dynamic_array&& other, const allocator_type& alloc)
210  {
211  clear();
212 
213  if (!is_static())
214  {
215  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
216  }
217 
218  reset_to_static();
219 
220  m_allocator = alloc;
221 
222  using mi = std::move_iterator<iterator>;
223  assign(mi{other.begin()}, mi{other.end()});
224 
225  other.reset_to_static();
226  }
230  constexpr ~basic_dynamic_array() noexcept
231  {
232  clear();
233 
234  if (!is_static() && mp_begin)
235  {
236  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
237  }
238 
239  reset_to_static();
240  }
241 
247  constexpr auto operator=(const basic_dynamic_array& rhs) -> basic_dynamic_array&
248  {
249  if (this != &rhs)
250  {
251  if (m_allocator != rhs.m_allocator)
252  {
253  clear();
254 
255  if (!is_static())
256  {
257  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
258  }
259 
260  reset_to_static();
261  }
262 
263  m_allocator = rhs.m_allocator;
264 
265  assign(rhs.begin(), rhs.end());
266  }
267 
268  return *this;
269  }
270 
276  constexpr auto operator=(basic_dynamic_array&& rhs) noexcept -> basic_dynamic_array&
277  {
278  if (m_allocator != rhs.allocator())
279  {
280  using move_it = std::move_iterator<iterator>;
281  assign(move_it{rhs.begin()}, move_it{rhs.end()});
282 
283  rhs.reset_to_static();
284  }
285  else
286  {
287  if (!rhs.is_static())
288  {
289  if (!is_static())
290  {
291  clear();
292 
293  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
294 
295  reset_to_static();
296  }
297 
298  m_size = rhs.size();
299  m_capacity = rhs.capacity();
300  mp_begin = rhs.mp_begin;
301  }
302  else
303  {
304  using move_it = std::move_iterator<iterator>;
305  assign(move_it{rhs.begin()}, move_it{rhs.end()});
306  }
307 
308  rhs.reset_to_static();
309  }
310 
311  return *this;
312  }
313 
319  constexpr auto operator=(std::initializer_list<Any> init_list) -> basic_dynamic_array&
320  {
321  assign(init_list);
322 
323  return *this;
324  }
325 
331  constexpr auto allocator() const noexcept -> allocator_type { return m_allocator; }
332 
343  constexpr auto lookup(size_type index) -> reference
344  {
345  Expects(index < m_size);
346  Expects(index >= 0);
347 
348  return mp_begin[index];
349  }
360  constexpr auto lookup(size_type index) const -> const_reference
361  {
362  Expects(index < m_size);
363 
364  return mp_begin[index];
365  }
366 
373  constexpr auto data() noexcept -> pointer { return pointer{&(*begin())}; }
380  constexpr auto data() const noexcept -> const_pointer { return const_pointer{&(*cbegin())}; }
381 
388  constexpr auto begin() noexcept -> iterator { return iterator{mp_begin}; }
395  constexpr auto begin() const noexcept -> const_iterator { return const_iterator{mp_begin}; }
402  constexpr auto cbegin() const noexcept -> const_iterator { return const_iterator{mp_begin}; }
403 
411  constexpr auto end() noexcept -> iterator { return iterator{mp_begin + m_size}; }
419  constexpr auto end() const noexcept -> const_iterator
420  {
421  return const_iterator{mp_begin + m_size};
422  }
430  constexpr auto cend() const noexcept -> const_iterator
431  {
432  return const_iterator{mp_begin + m_size};
433  }
434 
442  constexpr auto rbegin() noexcept -> reverse_iterator { return reverse_iterator{end()}; }
450  constexpr auto rbegin() const noexcept -> const_reverse_iterator
451  {
452  return const_reverse_iterator{cend()};
453  }
462  constexpr auto rcbegin() const noexcept -> const_reverse_iterator
463  {
464  return const_reverse_iterator{cend()};
465  }
466 
475  constexpr auto rend() noexcept -> reverse_iterator { return reverse_iterator{begin()}; }
484  constexpr auto rend() const noexcept -> const_reverse_iterator
485  {
486  return const_reverse_iterator{cbegin()};
487  }
496  constexpr auto rcend() const noexcept -> const_reverse_iterator
497  {
498  return const_reverse_iterator{cbegin()};
499  }
500 
506  [[nodiscard]] constexpr auto empty() const noexcept -> bool { return begin() == end(); };
512  [[nodiscard]] constexpr auto size() const noexcept -> size_type { return m_size; };
519  [[nodiscard]] constexpr auto capacity() const noexcept -> size_type { return m_capacity; };
529  constexpr void reserve(size_type new_cap)
530  {
531  if (new_cap > capacity())
532  {
533  grow(new_cap);
534  }
535  }
536 
540  constexpr void clear() noexcept
541  {
542  std::destroy(begin(), end());
543  m_size = 0;
544  }
545 
558  constexpr auto insert(const_iterator pos, const_reference value) -> iterator
559  {
560  Expects(pos >= cbegin());
561  Expects(pos <= cend());
562 
563  if (pos == cend())
564  {
565  append(value);
566 
567  return end() - 1;
568  }
569 
570  iterator new_pos;
571  if (size() >= capacity())
572  {
573  size_type offset = pos - cbegin();
574  grow();
575  new_pos = begin() + offset;
576  }
577  else
578  {
579  new_pos = begin() + (pos - cbegin());
580  }
581 
582  std::construct_at(offset(size()), std::move(*(end() - 1)));
583  std::move_backward(new_pos, end() - 1, end());
584 
585  ++m_size;
586 
587  const_pointer p_element = &value;
588  if (pointer{&(*new_pos)} <= p_element && pointer{&(*end())} > p_element)
589  {
590  ++p_element;
591  }
592 
593  *new_pos = *p_element;
594 
595  return new_pos;
596  }
597 
610  constexpr auto insert(const_iterator pos, value_type&& value) -> iterator
611  {
612  Expects(pos >= cbegin());
613  Expects(pos <= cend());
614 
615  if (pos == cend())
616  {
617  append(std::move(value));
618 
619  return end() - 1;
620  }
621 
622  iterator new_pos;
623  if (size() >= capacity())
624  {
625  size_type offset = pos - cbegin();
626  grow();
627  new_pos = begin() + offset;
628  }
629  else
630  {
631  new_pos = begin() + (pos - cbegin());
632  }
633 
634  construct(offset(size()), std::move(*(end() - 1)));
635 
636  std::move_backward(new_pos, end() - 1, end());
637 
638  ++m_size;
639 
640  pointer p_element = &value;
641  if (pointer{&(*new_pos)} <= p_element && pointer{&(*end())} > p_element)
642  {
643  ++p_element;
644  }
645 
646  *new_pos = std::move(*p_element);
647 
648  return new_pos;
649  }
662  template <typename... Args>
663  constexpr auto insert(const_iterator pos, Args... args) -> iterator
664  {
665  Expects(pos >= cbegin());
666  Expects(pos <= cend());
667 
668  if (pos == cend())
669  {
670  append(in_place, std::forward<Args>(args)...);
671 
672  return end() - 1;
673  }
674 
675  iterator new_pos;
676  if (size() >= capacity())
677  {
678  size_type offset = pos - cbegin();
679  grow();
680  new_pos = begin() + offset;
681  }
682  else
683  {
684  new_pos = begin() + (pos - cbegin());
685  }
686 
687  new (&(*end())) value_type(std::move(*(end() - 1)));
688 
689  std::move_backward(new_pos, end() - 1, end());
690 
691  ++m_size;
692 
693  *new_pos = value_type(std::forward<Args>(args)...);
694 
695  return new_pos;
696  }
710  constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
711  {
712  Expects(pos >= cbegin());
713  Expects(pos <= cend());
714 
715  size_type start_index = pos - cbegin();
716 
717  if (pos == cend())
718  {
719  if (size() + count >= capacity())
720  {
721  grow(size() + count);
722  }
723 
724  std::uninitialized_fill_n(end(), count, value);
725 
726  m_size += count;
727 
728  return begin() + start_index;
729  }
730 
731  reserve(size() + count);
732 
733  iterator updated_pos = begin() + start_index;
734 
735  if (iterator old_end = end(); end() - updated_pos >= count)
736  {
737  std::uninitialized_move(end() - count, end(), end());
738 
739  m_size += count;
740 
741  std::move_backward(updated_pos, old_end - count, old_end);
742  std::fill_n(updated_pos, count, value);
743  }
744  else
745  {
746  size_type move_count = old_end - updated_pos;
747  m_size += count;
748 
749  std::uninitialized_move(updated_pos, old_end, end() - move_count);
750  std::fill_n(updated_pos, move_count, value);
751  std::uninitialized_fill_n(old_end, count - move_count, value);
752  }
753 
754  return updated_pos;
755  }
756 
770  template <std::input_iterator InputIt>
771  constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
772  {
773  Expects(pos >= cbegin());
774  Expects(pos <= cend());
775 
776  size_type start_index = pos - cbegin();
777  difference_type count = std::distance(first, last);
778 
779  if (pos == cend())
780  {
781  if (size() + count >= capacity())
782  {
783  grow(size() + count);
784  }
785 
786  std::uninitialized_copy(first, last, end());
787 
788  m_size += count;
789 
790  return begin() + start_index;
791  }
792 
793  reserve(size() + count);
794 
795  iterator updated_pos = begin() + start_index;
796  if (iterator old_end = end(); end() - updated_pos >= count)
797  {
798  std::uninitialized_move(end() - count, end(), end());
799 
800  m_size += count;
801 
802  std::move_backward(updated_pos, old_end - count, old_end);
803  std::copy(first, last, updated_pos);
804  }
805  else
806  {
807  size_type move_count = old_end - updated_pos;
808  m_size += count;
809 
810  std::uninitialized_move(updated_pos, old_end, end() - move_count);
811 
812  for (auto it = updated_pos; count > 0; --count)
813  {
814  *it = *first;
815 
816  ++it;
817  ++first;
818  }
819 
820  std::uninitialized_copy(first, last, old_end);
821  }
822 
823  return updated_pos;
824  }
825 
838  constexpr auto insert(const_iterator pos, std::initializer_list<value_type> init_list)
839  -> iterator
840  {
841  return insert(pos, init_list.begin(), init_list.end());
842  }
843 
852  constexpr auto erase(const_iterator pos) -> iterator
853  {
854  Expects(pos >= cbegin());
855  Expects(pos <= cend());
856 
857  if (pos == cend())
858  {
859  return end();
860  }
861 
862  auto it = begin() + (pos - cbegin());
863 
864  std::move(it + 1, end(), it);
865 
866  pop_back();
867 
868  return it;
869  }
884  constexpr auto erase(const_iterator first, const_iterator last) -> iterator
885  {
886  Expects(first >= cbegin());
887  Expects(last <= cend());
888  Expects(first >= last);
889 
890  if (first == last)
891  {
892  return begin() + (first - cbegin());
893  }
894 
895  size_type const distance = std::distance(first, last);
896 
897  iterator it_f = begin() + (first - cbegin());
898  iterator it_l = begin() + (last - cbegin());
899  iterator it = std::move(it_l, end(), it_f);
900 
901  std::destroy(it, end());
902 
903  m_size -= distance;
904 
905  return it_f;
906  }
907 
914  constexpr void append(const value_type& value)
915  {
916  if (size() >= capacity())
917  {
918  grow();
919  }
920 
921  construct(mp_begin + size(), value);
922 
923  ++m_size;
924  }
931  constexpr void append(value_type&& value)
932  {
933  if (size() >= capacity())
934  {
935  grow();
936  }
937 
938  construct(mp_begin + size(), std::move(value));
939 
940  ++m_size;
941  }
948  template <typename... Args>
949  requires std::constructible_from<value_type, Args...> constexpr auto append(in_place_t,
950  Args&&... args)
951  -> reference
952  {
953  if (size() >= capacity())
954  {
955  grow();
956  }
957 
958  std::construct_at(offset(size()), std::forward<Args>(args)...);
959 
960  ++m_size;
961 
962  return *(end() - 1);
963  }
964 
970  constexpr void pop_back()
971  {
972  Expects(size() != 0);
973 
974  std::destroy_at(offset(size()));
975  --m_size;
976  };
977 
985  constexpr void resize(size_type count)
986  {
987  if (size() > count)
988  {
989  std::destroy(begin() + count, end());
990  m_size = count;
991  }
992  else if (size() < count)
993  {
994  if (capacity() < count)
995  {
996  grow(count);
997  }
998 
999  for (size_type i = size(); i < count; ++i)
1000  {
1001  construct(offset(i), value_type{});
1002  }
1003 
1004  m_size = count;
1005  }
1006  }
1015  constexpr void resize(size_type count, const_reference value)
1016  {
1017  if (size() > count)
1018  {
1019  std::destroy(begin() + count, end());
1020  m_size = count;
1021  }
1022  else if (size() < count)
1023  {
1024  if (capacity() < count)
1025  {
1026  grow(count);
1027  }
1028 
1029  std::uninitialized_fill(end(), begin() + count, value);
1030 
1031  m_size = count;
1032  }
1033  }
1034 
1035  private:
1036  [[nodiscard]] constexpr auto is_static() const noexcept -> bool
1037  {
1038  return mp_begin == get_first_element();
1039  }
1040 
1041  constexpr auto get_first_element() const -> pointer
1042  {
1043  return const_cast<pointer>(reinterpret_cast<const_pointer>(&m_static_storage)); // NOLINT
1044  }
1045 
1046  constexpr void grow(size_type min_size = 0)
1047  {
1048  const auto new_capacity = compute_new_capacity(std::max(m_capacity + 1, min_size));
1049  auto* new_elements = m_allocator.allocate(count_t{new_capacity});
1050 
1051  if constexpr (std::is_move_constructible_v<value_type>)
1052  {
1053  std::uninitialized_move(begin(), end(), iterator{new_elements});
1054  }
1055  else
1056  {
1057  std::uninitialized_copy(begin(), end(), iterator{new_elements});
1058  }
1059 
1060  std::destroy(begin(), end());
1061 
1062  if (!is_static())
1063  {
1064  if (mp_begin)
1065  {
1066  m_allocator.deallocate(gsl::make_not_null(mp_begin), count_t{capacity()});
1067  }
1068  }
1069 
1070  mp_begin = new_elements;
1071  m_capacity = new_capacity;
1072  }
1073 
1074  constexpr void reset_to_static()
1075  {
1076  mp_begin = get_first_element();
1077  m_size = 0;
1078  m_capacity = Size;
1079  }
1080 
1081  constexpr void assign(size_type count, const_reference value)
1082  {
1083  clear();
1084 
1085  if (count > m_capacity)
1086  {
1087  grow(count);
1088  }
1089 
1090  m_size = count;
1091 
1092  std::uninitialized_fill(begin(), end(), value);
1093  }
1094 
1095  template <std::input_iterator InputIt>
1096  constexpr void assign(InputIt first, InputIt last)
1097  {
1098  clear();
1099 
1100  const auto new_count = static_cast<size_type>(std::distance(first, last));
1101  if (new_count > capacity())
1102  {
1103  grow(new_count);
1104  }
1105 
1106  m_size = new_count;
1107 
1108  std::uninitialized_copy(first, last, begin());
1109  }
1110 
1111  constexpr void assign(std::initializer_list<value_type> initializer_list)
1112  {
1113  assign(initializer_list.begin(), initializer_list.end());
1114  }
1115 
1116  constexpr auto offset(size_type i) noexcept -> pointer { return mp_begin + i; }
1117  constexpr auto offset(size_type i) const noexcept -> const_pointer { return mp_begin + i; }
1118 
1119  static constexpr auto compute_new_capacity(size_type min_capacity) -> size_type
1120  {
1121  constexpr auto max_digits = std::numeric_limits<size_type>::digits;
1122  constexpr auto max_capacity = size_type{1} << (max_digits - 1);
1123 
1124  if (min_capacity > max_capacity)
1125  {
1126  return max_capacity;
1127  }
1128 
1129  --min_capacity;
1130 
1131  for (size_type i = 1; i < max_digits; i *= 2)
1132  {
1133  min_capacity |= min_capacity >> i;
1134  }
1135 
1136  return ++min_capacity;
1137  }
1138 
1139  private:
1140  pointer mp_begin{nullptr};
1141 
1142  alignas(alignof(Any)) std::array<std::byte, sizeof(Any) * Size> m_static_storage;
1143 
1144  size_type m_size{0u};
1145  size_type m_capacity{0u};
1146 
1147  allocator_type m_allocator;
1148  };
1149 
1150  template <std::equality_comparable Any, i64_t SizeOne, i64_t SizeTwo, typename allocator>
1151  constexpr auto operator==(const basic_dynamic_array<Any, SizeOne, allocator>& lhs,
1152  const basic_dynamic_array<Any, SizeTwo, allocator>& rhs) -> bool
1153  {
1154  return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs));
1155  }
1156 
1157  template <typename Any, i64_t SizeOne, i64_t SizeTwo, typename allocator>
1158  constexpr auto operator<=>(const basic_dynamic_array<Any, SizeOne, allocator>& lhs,
1159  const basic_dynamic_array<Any, SizeTwo, allocator>& rhs)
1160  {
1161  return std::lexicographical_compare_three_way(std::begin(lhs), std::end(lhs), std::begin(rhs),
1162  std::end(rhs), detail::synth_three_way);
1163  }
1164 
1165  template <typename Iter, i64_t Size = 0,
1166  typename Allocator = memory_allocator<typename std::iterator_traits<Iter>::value_type>>
1167  basic_dynamic_array(Iter, Iter)
1168  -> basic_dynamic_array<typename std::iterator_traits<Iter>::value_type, Size, Allocator>;
1169 
1170  template <typename Any, typename... U, typename Allocator = memory_allocator<Any>>
1171  basic_dynamic_array(Any, U...) -> basic_dynamic_array<Any, 1 + sizeof...(U), Allocator>;
1172 
1182  template <typename Any, i64_t Size>
1184  {
1186 
1187  public:
1188  using value_type = Any;
1189  using size_type = typename underlying_type::size_type;
1190  using difference_type = std::ptrdiff_t;
1191  using allocator_type = typename underlying_type::allocator_type;
1192  using reference = value_type&;
1193  using const_reference = const value_type&;
1194  using pointer = typename std::allocator_traits<allocator_type>::pointer;
1195  using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
1196  using iterator = typename underlying_type::iterator;
1197  using const_iterator = typename underlying_type::const_iterator;
1198  using reverse_iterator = std::reverse_iterator<iterator>;
1199  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1200 
1201  public:
1205  constexpr small_dynamic_array() noexcept(noexcept(underlying_type{})) = default;
1212  constexpr small_dynamic_array(size_type count, const_reference value) :
1213  m_underlying{count, value}
1214  {}
1220  constexpr small_dynamic_array(std::initializer_list<Any> init) : m_underlying{init} {}
1227  template <std::input_iterator InputIt>
1228  constexpr small_dynamic_array(InputIt first, InputIt last) : m_underlying{first, last}
1229  {}
1230 
1236  constexpr auto operator=(std::initializer_list<Any> init_list) -> small_dynamic_array&
1237  {
1238  m_underlying = init_list;
1239 
1240  return *this;
1241  }
1242 
1248  constexpr auto allocator() const noexcept -> allocator_type
1249  {
1250  return m_underlying.allocator();
1251  }
1252 
1263  constexpr auto lookup(size_type index) -> reference { return m_underlying.lookup(index); }
1274  constexpr auto lookup(size_type index) const -> const_reference
1275  {
1276  return m_underlying.lookup(index);
1277  }
1278 
1285  constexpr auto data() noexcept -> pointer { return m_underlying.data(); }
1292  constexpr auto data() const noexcept -> const_pointer { return m_underlying.data(); }
1293 
1300  constexpr auto begin() noexcept -> iterator { return m_underlying.begin(); }
1307  constexpr auto begin() const noexcept -> const_iterator { return m_underlying.begin(); }
1314  constexpr auto cbegin() const noexcept -> const_iterator { return m_underlying.cbegin(); }
1315 
1323  constexpr auto end() noexcept -> iterator { return m_underlying.end(); }
1331  constexpr auto end() const noexcept -> const_iterator { return m_underlying.end(); }
1339  constexpr auto cend() const noexcept -> const_iterator { return m_underlying.cend(); }
1340 
1348  constexpr auto rbegin() noexcept -> reverse_iterator { return m_underlying.rbegin(); }
1356  constexpr auto rbegin() const noexcept -> const_reverse_iterator
1357  {
1358  return m_underlying.rbegin();
1359  }
1368  constexpr auto rcbegin() const noexcept -> const_reverse_iterator
1369  {
1370  return m_underlying.rcbegin();
1371  }
1372 
1381  constexpr auto rend() noexcept -> reverse_iterator { return m_underlying.end(); }
1390  constexpr auto rend() const noexcept -> const_reverse_iterator { return m_underlying.rend(); }
1399  constexpr auto rcend() const noexcept -> const_reverse_iterator
1400  {
1401  return m_underlying.rcend();
1402  }
1403 
1409  [[nodiscard]] constexpr auto empty() const noexcept -> bool { return m_underlying.empty(); };
1415  [[nodiscard]] constexpr auto size() const noexcept -> size_type
1416  {
1417  return m_underlying.size();
1418  };
1425  [[nodiscard]] constexpr auto capacity() const noexcept -> size_type
1426  {
1427  return m_underlying.capacity();
1428  };
1438  constexpr void reserve(size_type new_cap) { m_underlying.reserve(new_cap); }
1439 
1443  constexpr void clear() noexcept { m_underlying.clear(); }
1444 
1457  constexpr auto insert(const_iterator pos, const_reference value) -> iterator
1458  {
1459  return m_underlying.insert(pos, value);
1460  }
1461 
1474  constexpr auto insert(const_iterator pos, value_type&& value) -> iterator
1475  {
1476  return m_underlying.insert(pos, std::move(value));
1477  }
1490  template <typename... Args>
1491  constexpr auto insert(const_iterator pos, Args... args) -> iterator
1492  {
1493  return m_underlying.insert(pos, std::forward<Args>(args)...);
1494  }
1508  constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
1509  {
1510  return m_underlying.insert(pos, count, value);
1511  }
1512 
1526  template <std::input_iterator InputIt>
1527  constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
1528  {
1529  return m_underlying.insert(pos, first, last);
1530  }
1531 
1544  constexpr auto insert(const_iterator pos, std::initializer_list<value_type> init_list)
1545  -> iterator
1546  {
1547  return m_underlying(pos, init_list);
1548  }
1549 
1558  constexpr auto erase(const_iterator pos) -> iterator { return m_underlying.erase(pos); }
1573  constexpr auto erase(const_iterator first, const_iterator last) -> iterator
1574  {
1575  return m_underlying.erase(first, last);
1576  }
1577 
1584  constexpr void append(const value_type& value) { m_underlying.append(value); }
1591  constexpr void append(value_type&& value) { m_underlying.append(std::move(value)); }
1598  template <typename... Args>
1599  requires std::constructible_from<value_type, Args...> constexpr auto append(in_place_t,
1600  Args&&... args)
1601  -> reference
1602  {
1603  return m_underlying.append(in_place, std::forward<Args>(args)...);
1604  }
1605 
1611  constexpr void pop_back() { return m_underlying.pop_back(); };
1612 
1620  constexpr void resize(size_type count) { m_underlying.resize(count); }
1629  constexpr void resize(size_type count, const_reference value)
1630  {
1631  m_underlying.resize(count, value);
1632  }
1633 
1634  private:
1635  underlying_type m_underlying;
1636  };
1637 
1638  template <std::equality_comparable Any, i64_t SizeOne, i64_t SizeTwo>
1639  constexpr auto operator==(const small_dynamic_array<Any, SizeOne>& lhs,
1640  const small_dynamic_array<Any, SizeTwo>& rhs) -> bool
1641  {
1642  return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs));
1643  }
1644 
1645  template <typename Any, i64_t SizeOne, i64_t SizeTwo>
1646  constexpr auto operator<=>(const small_dynamic_array<Any, SizeOne>& lhs,
1647  const small_dynamic_array<Any, SizeTwo>& rhs)
1648  {
1649  return std::lexicographical_compare_three_way(std::begin(lhs), std::end(lhs), std::begin(rhs),
1650  std::end(rhs), detail::synth_three_way);
1651  }
1652 
1653  template <typename Iter, i64_t Size = 0>
1654  small_dynamic_array(Iter, Iter)
1655  -> small_dynamic_array<typename std::iterator_traits<Iter>::value_type, Size>;
1656 
1657  template <typename Any, typename... U>
1658  small_dynamic_array(Any, U...) -> small_dynamic_array<Any, 1 + sizeof...(U)>;
1659 
1668  template <typename Any>
1670  {
1672 
1673  public:
1674  using value_type = Any;
1675  using size_type = typename underlying_type::size_type;
1676  using difference_type = std::ptrdiff_t;
1677  using allocator_type = typename underlying_type::allocator_type;
1678  using reference = value_type&;
1679  using const_reference = const value_type&;
1680  using pointer = typename allocator_type::pointer;
1681  using const_pointer = typename allocator_type::const_pointer;
1682  using iterator = typename underlying_type::iterator;
1683  using const_iterator = typename underlying_type::const_iterator;
1684  using reverse_iterator = std::reverse_iterator<iterator>;
1685  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1686 
1687  public:
1691  constexpr dynamic_array() noexcept(noexcept(underlying_type{})) = default;
1698  constexpr dynamic_array(size_type count, const_reference value) : m_underlying{count, value}
1699  {}
1705  constexpr dynamic_array(std::initializer_list<Any> init) : m_underlying{init} {}
1712  template <std::input_iterator InputIt>
1713  constexpr dynamic_array(InputIt first, InputIt last) : m_underlying{first, last}
1714  {}
1715 
1721  constexpr auto operator=(std::initializer_list<Any> init_list) -> dynamic_array&
1722  {
1723  m_underlying = init_list;
1724 
1725  return *this;
1726  }
1727 
1733  constexpr auto allocator() const noexcept -> allocator_type
1734  {
1735  return m_underlying.allocator();
1736  }
1737 
1748  constexpr auto lookup(size_type index) -> reference { return m_underlying.lookup(index); }
1759  constexpr auto lookup(size_type index) const -> const_reference
1760  {
1761  return m_underlying.lookup(index);
1762  }
1763 
1770  constexpr auto data() noexcept -> pointer { return m_underlying.data(); }
1777  constexpr auto data() const noexcept -> const_pointer { return m_underlying.data(); }
1778 
1785  constexpr auto begin() noexcept -> iterator { return m_underlying.begin(); }
1792  constexpr auto begin() const noexcept -> const_iterator { return m_underlying.begin(); }
1799  constexpr auto cbegin() const noexcept -> const_iterator { return m_underlying.cbegin(); }
1800 
1808  constexpr auto end() noexcept -> iterator { return m_underlying.end(); }
1816  constexpr auto end() const noexcept -> const_iterator { return m_underlying.end(); }
1824  constexpr auto cend() const noexcept -> const_iterator { return m_underlying.cend(); }
1825 
1833  constexpr auto rbegin() noexcept -> reverse_iterator { return m_underlying.rbegin(); }
1841  constexpr auto rbegin() const noexcept -> const_reverse_iterator
1842  {
1843  return m_underlying.rbegin();
1844  }
1853  constexpr auto rcbegin() const noexcept -> const_reverse_iterator
1854  {
1855  return m_underlying.rcbegin();
1856  }
1857 
1866  constexpr auto rend() noexcept -> reverse_iterator { return m_underlying.end(); }
1875  constexpr auto rend() const noexcept -> const_reverse_iterator { return m_underlying.rend(); }
1884  constexpr auto rcend() const noexcept -> const_reverse_iterator
1885  {
1886  return m_underlying.rcend();
1887  }
1888 
1894  [[nodiscard]] constexpr auto empty() const noexcept -> bool { return m_underlying.empty(); };
1900  [[nodiscard]] constexpr auto size() const noexcept -> size_type
1901  {
1902  return m_underlying.size();
1903  };
1910  [[nodiscard]] constexpr auto capacity() const noexcept -> size_type
1911  {
1912  return m_underlying.capacity();
1913  };
1923  constexpr void reserve(size_type new_cap) { m_underlying.reserve(new_cap); }
1924 
1928  constexpr void clear() noexcept { m_underlying.clear(); }
1929 
1942  constexpr auto insert(const_iterator pos, const_reference value) -> iterator
1943  {
1944  return m_underlying.insert(pos, value);
1945  }
1946 
1959  constexpr auto insert(const_iterator pos, value_type&& value) -> iterator
1960  {
1961  return m_underlying.insert(pos, std::move(value));
1962  }
1975  template <typename... Args>
1976  constexpr auto insert(const_iterator pos, Args... args) -> iterator
1977  {
1978  return m_underlying.insert(pos, std::forward<Args>(args)...);
1979  }
1993  constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
1994  {
1995  return m_underlying.insert(pos, count, value);
1996  }
1997 
2011  template <std::input_iterator InputIt>
2012  constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
2013  {
2014  return m_underlying.insert(pos, first, last);
2015  }
2016 
2029  constexpr auto insert(const_iterator pos, std::initializer_list<value_type> init_list)
2030  -> iterator
2031  {
2032  return m_underlying(pos, init_list);
2033  }
2034 
2043  constexpr auto erase(const_iterator pos) -> iterator { return m_underlying.erase(pos); }
2058  constexpr auto erase(const_iterator first, const_iterator last) -> iterator
2059  {
2060  return m_underlying.erase(first, last);
2061  }
2062 
2069  constexpr void append(const value_type& value) { m_underlying.append(value); }
2076  constexpr void append(value_type&& value) { m_underlying.append(std::move(value)); }
2083  template <typename... Args>
2084  requires std::constructible_from<value_type, Args...> constexpr auto append(in_place_t,
2085  Args&&... args)
2086  -> reference
2087  {
2088  return m_underlying.append(in_place, std::forward<Args>(args)...);
2089  }
2090 
2096  constexpr void pop_back() { return m_underlying.pop_back(); };
2097 
2105  constexpr void resize(size_type count) { m_underlying.resize(count); }
2114  constexpr void resize(size_type count, const_reference value)
2115  {
2116  m_underlying.resize(count, value);
2117  }
2118 
2119  private:
2120  underlying_type m_underlying;
2121  };
2122 
2123  template <std::equality_comparable Any>
2124  constexpr auto operator==(const dynamic_array<Any>& lhs, const dynamic_array<Any>& rhs) -> bool
2125  {
2126  return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs));
2127  }
2128 
2129  template <typename Any>
2130  constexpr auto operator<=>(const dynamic_array<Any>& lhs, const dynamic_array<Any>& rhs)
2131  {
2132  return std::lexicographical_compare_three_way(std::begin(lhs), std::end(lhs), std::begin(rhs),
2133  std::end(rhs), detail::synth_three_way);
2134  }
2135 
2136  template <typename Iter>
2137  dynamic_array(Iter, Iter) -> dynamic_array<typename std::iterator_traits<Iter>::value_type>;
2138 } // namespace caramel
A resizable array with a small statically allocated storage buffer.
Definition: dynamic_array.hpp:70
constexpr basic_dynamic_array(const basic_dynamic_array &other)
Construct the container using the contents of other.
Definition: dynamic_array.hpp:145
constexpr basic_dynamic_array(size_type count, const_reference value, const allocator_type &allocator=allocator_type{})
Construct the container with count copies of elements with value value.
Definition: dynamic_array.hpp:105
constexpr void reserve(size_type new_cap)
Increase the capacity of the vector to a value that's greater or equal to new_cap....
Definition: dynamic_array.hpp:529
constexpr auto insert(const_iterator pos, const_reference value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:558
constexpr auto data() const noexcept -> const_pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:380
constexpr auto rbegin() noexcept -> reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:442
constexpr auto cend() const noexcept -> const_iterator
Returns an it iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:430
constexpr auto erase(const_iterator pos) -> iterator
Erases the specified element from the container.
Definition: dynamic_array.hpp:852
constexpr void append(value_type &&value)
Appends the given element value to the end of the container. Value is moved into the new element.
Definition: dynamic_array.hpp:931
constexpr auto data() noexcept -> pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:373
constexpr auto rend() noexcept -> reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:475
constexpr basic_dynamic_array(const basic_dynamic_array &other, const allocator_type &allocator)
Construct the container using the contents of other. using allocator as the allocator.
Definition: dynamic_array.hpp:160
constexpr auto cbegin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:402
constexpr auto end() noexcept -> iterator
Get an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:411
constexpr auto capacity() const noexcept -> size_type
Check the number of elements that the basic_dynamic_array has currently allocated space for.
Definition: dynamic_array.hpp:519
constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
Inserts elements from a range [first, last) before pos.
Definition: dynamic_array.hpp:771
constexpr auto end() const noexcept -> const_iterator
Return an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:419
constexpr void pop_back()
Removes the last element in the container.
Definition: dynamic_array.hpp:970
constexpr basic_dynamic_array(std::initializer_list< Any > init, const allocator_type &allocator=allocator_type{})
Construct the container with the contents of the initializer list init.
Definition: dynamic_array.hpp:119
constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
Inserts count elements from a specified value.
Definition: dynamic_array.hpp:710
constexpr basic_dynamic_array(basic_dynamic_array &&other, const allocator_type &alloc)
Construct the container with the contents of the other using move semantic. Using alloc as the alloca...
Definition: dynamic_array.hpp:209
constexpr auto insert(const_iterator pos, Args... args) -> iterator
Insert a new element into the container directly before pos. The element is constructed in-place usin...
Definition: dynamic_array.hpp:663
constexpr basic_dynamic_array() noexcept=default
Default constructor.
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Returns a reverse_iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:450
constexpr auto empty() const noexcept -> bool
Check if the basic_dynamic_array is empty.
Definition: dynamic_array.hpp:506
constexpr auto insert(const_iterator pos, std::initializer_list< value_type > init_list) -> iterator
Insert elements from an initializer_list before the position pos.
Definition: dynamic_array.hpp:838
constexpr auto insert(const_iterator pos, value_type &&value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:610
constexpr void resize(size_type count, const_reference value)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:1015
constexpr auto operator=(basic_dynamic_array &&rhs) noexcept -> basic_dynamic_array &
Replaces the contents with those of other using move semantics.
Definition: dynamic_array.hpp:276
constexpr auto begin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:395
constexpr auto lookup(size_type index) const -> const_reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:360
constexpr auto begin() noexcept -> iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:388
constexpr auto erase(const_iterator first, const_iterator last) -> iterator
Erases the specified elements from the container.
Definition: dynamic_array.hpp:884
constexpr auto allocator() const noexcept -> allocator_type
Returns the allocator associated with the container.
Definition: dynamic_array.hpp:331
constexpr basic_dynamic_array(basic_dynamic_array &&other) noexcept
Construct the container with the contents of the other using move semantic. After move,...
Definition: dynamic_array.hpp:194
constexpr auto rcbegin() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:462
constexpr auto rend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:484
constexpr auto size() const noexcept -> size_type
Check the number of elements stored in the basic_dynamic_array.
Definition: dynamic_array.hpp:512
constexpr basic_dynamic_array(InputIt first, InputIt last, const allocator_type &allocator=allocator_type{})
Construct the container with the contents of the range [first, last)
Definition: dynamic_array.hpp:133
constexpr void append(const value_type &value)
Appends the given element value to the end of the container. The new element is initialized as a copy...
Definition: dynamic_array.hpp:914
constexpr void clear() noexcept
Erases all elements from the container, After this call, size() returs zero.
Definition: dynamic_array.hpp:540
constexpr ~basic_dynamic_array() noexcept
Destructor.
Definition: dynamic_array.hpp:230
constexpr auto operator=(std::initializer_list< Any > init_list) -> basic_dynamic_array &
Replaces the contents with those identified by initializer list init_list.
Definition: dynamic_array.hpp:319
constexpr auto operator=(const basic_dynamic_array &rhs) -> basic_dynamic_array &
Replaces the contents with an copy of the contents of rhs.
Definition: dynamic_array.hpp:247
constexpr auto rcend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:496
requires constexpr std::constructible_from< value_type, Args... > auto append(in_place_t, Args &&... args) -> reference
Appends the given element value to the end of the container. The element is constructed in-place usin...
Definition: dynamic_array.hpp:949
constexpr auto lookup(size_type index) -> reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:343
constexpr void resize(size_type count)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:985
A resizable array.
Definition: dynamic_array.hpp:1670
constexpr auto cend() const noexcept -> const_iterator
Returns an it iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1824
constexpr auto size() const noexcept -> size_type
Check the number of elements stored in the basic_dynamic_array.
Definition: dynamic_array.hpp:1900
constexpr auto begin() noexcept -> iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1785
constexpr auto empty() const noexcept -> bool
Check if the basic_dynamic_array is empty.
Definition: dynamic_array.hpp:1894
constexpr void reserve(size_type new_cap)
Increase the capacity of the vector to a value that's greater or equal to new_cap....
Definition: dynamic_array.hpp:1923
constexpr auto operator=(std::initializer_list< Any > init_list) -> dynamic_array &
Replaces the contents with those identified by initializer list init_list.
Definition: dynamic_array.hpp:1721
constexpr auto rcend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1884
constexpr dynamic_array() noexcept(noexcept(underlying_type{}))=default
Default constructor.
constexpr auto allocator() const noexcept -> allocator_type
Returns the allocator associated with the container.
Definition: dynamic_array.hpp:1733
constexpr auto rcbegin() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1853
constexpr void resize(size_type count)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:2105
constexpr auto insert(const_iterator pos, std::initializer_list< value_type > init_list) -> iterator
Insert elements from an initializer_list before the position pos.
Definition: dynamic_array.hpp:2029
constexpr dynamic_array(size_type count, const_reference value)
Construct the container with count copies of elements with value value.
Definition: dynamic_array.hpp:1698
constexpr void resize(size_type count, const_reference value)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:2114
constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
Inserts count elements from a specified value.
Definition: dynamic_array.hpp:1993
constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
Inserts elements from a range [first, last) before pos.
Definition: dynamic_array.hpp:2012
constexpr dynamic_array(std::initializer_list< Any > init)
Construct the container with the contents of the initializer list init.
Definition: dynamic_array.hpp:1705
constexpr auto rend() noexcept -> reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1866
constexpr auto erase(const_iterator first, const_iterator last) -> iterator
Erases the specified elements from the container.
Definition: dynamic_array.hpp:2058
constexpr auto end() noexcept -> iterator
Get an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1808
constexpr void append(value_type &&value)
Appends the given element value to the end of the container. Value is moved into the new element.
Definition: dynamic_array.hpp:2076
constexpr void pop_back()
Removes the last element in the container.
Definition: dynamic_array.hpp:2096
constexpr auto insert(const_iterator pos, Args... args) -> iterator
Insert a new element into the container directly before pos. The element is constructed in-place usin...
Definition: dynamic_array.hpp:1976
constexpr auto lookup(size_type index) const -> const_reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:1759
constexpr auto data() const noexcept -> const_pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:1777
requires constexpr std::constructible_from< value_type, Args... > auto append(in_place_t, Args &&... args) -> reference
Appends the given element value to the end of the container. The element is constructed in-place usin...
Definition: dynamic_array.hpp:2084
constexpr auto capacity() const noexcept -> size_type
Check the number of elements that the basic_dynamic_array has currently allocated space for.
Definition: dynamic_array.hpp:1910
constexpr void append(const value_type &value)
Appends the given element value to the end of the container. The new element is initialized as a copy...
Definition: dynamic_array.hpp:2069
constexpr auto end() const noexcept -> const_iterator
Return an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1816
constexpr dynamic_array(InputIt first, InputIt last)
Construct the container with the contents of the range [first, last)
Definition: dynamic_array.hpp:1713
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Returns a reverse_iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1841
constexpr auto begin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1792
constexpr auto insert(const_iterator pos, value_type &&value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:1959
constexpr void clear() noexcept
Erases all elements from the container, After this call, size() returs zero.
Definition: dynamic_array.hpp:1928
constexpr auto lookup(size_type index) -> reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:1748
constexpr auto erase(const_iterator pos) -> iterator
Erases the specified element from the container.
Definition: dynamic_array.hpp:2043
constexpr auto rend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1875
constexpr auto insert(const_iterator pos, const_reference value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:1942
constexpr auto cbegin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1799
constexpr auto data() noexcept -> pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:1770
constexpr auto rbegin() noexcept -> reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1833
Definition: memory_allocator.hpp:15
Definition: random_iterator.hpp:11
A resizable array with a small statically allocated storage buffer.
Definition: dynamic_array.hpp:1184
constexpr auto rcend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1399
constexpr auto cend() const noexcept -> const_iterator
Returns an it iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1339
constexpr auto data() const noexcept -> const_pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:1292
constexpr auto erase(const_iterator pos) -> iterator
Erases the specified element from the container.
Definition: dynamic_array.hpp:1558
constexpr auto insert(const_iterator pos, InputIt first, InputIt last) -> iterator
Inserts elements from a range [first, last) before pos.
Definition: dynamic_array.hpp:1527
constexpr auto erase(const_iterator first, const_iterator last) -> iterator
Erases the specified elements from the container.
Definition: dynamic_array.hpp:1573
constexpr auto lookup(size_type index) const -> const_reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:1274
constexpr auto insert(const_iterator pos, const_reference value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:1457
constexpr void resize(size_type count, const_reference value)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:1629
constexpr small_dynamic_array(size_type count, const_reference value)
Construct the container with count copies of elements with value value.
Definition: dynamic_array.hpp:1212
requires constexpr std::constructible_from< value_type, Args... > auto append(in_place_t, Args &&... args) -> reference
Appends the given element value to the end of the container. The element is constructed in-place usin...
Definition: dynamic_array.hpp:1599
constexpr auto rbegin() const noexcept -> const_reverse_iterator
Returns a reverse_iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1356
constexpr void resize(size_type count)
Resizes the container to contain count elements. If the current size is greater than count,...
Definition: dynamic_array.hpp:1620
constexpr auto lookup(size_type index) -> reference
Access the object stored at a specific index.
Definition: dynamic_array.hpp:1263
constexpr small_dynamic_array(InputIt first, InputIt last)
Construct the container with the contents of the range [first, last)
Definition: dynamic_array.hpp:1228
constexpr auto rbegin() noexcept -> reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1348
constexpr auto insert(const_iterator pos, Args... args) -> iterator
Insert a new element into the container directly before pos. The element is constructed in-place usin...
Definition: dynamic_array.hpp:1491
constexpr auto rcbegin() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the first element of the reversed basic_dynamic_array....
Definition: dynamic_array.hpp:1368
constexpr auto size() const noexcept -> size_type
Check the number of elements stored in the basic_dynamic_array.
Definition: dynamic_array.hpp:1415
constexpr auto allocator() const noexcept -> allocator_type
Returns the allocator associated with the container.
Definition: dynamic_array.hpp:1248
constexpr void clear() noexcept
Erases all elements from the container, After this call, size() returs zero.
Definition: dynamic_array.hpp:1443
constexpr auto data() noexcept -> pointer
Access the data stored by the container.
Definition: dynamic_array.hpp:1285
constexpr auto rend() const noexcept -> const_reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1390
constexpr auto begin() noexcept -> iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1300
constexpr small_dynamic_array(std::initializer_list< Any > init)
Construct the container with the contents of the initializer list init.
Definition: dynamic_array.hpp:1220
constexpr auto capacity() const noexcept -> size_type
Check the number of elements that the basic_dynamic_array has currently allocated space for.
Definition: dynamic_array.hpp:1425
constexpr auto insert(const_iterator pos, std::initializer_list< value_type > init_list) -> iterator
Insert elements from an initializer_list before the position pos.
Definition: dynamic_array.hpp:1544
constexpr void append(value_type &&value)
Appends the given element value to the end of the container. Value is moved into the new element.
Definition: dynamic_array.hpp:1591
constexpr auto cbegin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1314
constexpr auto rend() noexcept -> reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed basic_dynamic_ar...
Definition: dynamic_array.hpp:1381
constexpr auto insert(const_iterator pos, size_type count, const_reference value) -> iterator
Inserts count elements from a specified value.
Definition: dynamic_array.hpp:1508
constexpr void reserve(size_type new_cap)
Increase the capacity of the vector to a value that's greater or equal to new_cap....
Definition: dynamic_array.hpp:1438
constexpr small_dynamic_array() noexcept(noexcept(underlying_type{}))=default
Default constructor.
constexpr auto end() const noexcept -> const_iterator
Return an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1331
constexpr void pop_back()
Removes the last element in the container.
Definition: dynamic_array.hpp:1611
constexpr void append(const value_type &value)
Appends the given element value to the end of the container. The new element is initialized as a copy...
Definition: dynamic_array.hpp:1584
constexpr auto end() noexcept -> iterator
Get an iterator to the element following the last element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1323
constexpr auto operator=(std::initializer_list< Any > init_list) -> small_dynamic_array &
Replaces the contents with those identified by initializer list init_list.
Definition: dynamic_array.hpp:1236
constexpr auto begin() const noexcept -> const_iterator
Returns an iterator to the first element of the basic_dynamic_array.
Definition: dynamic_array.hpp:1307
constexpr auto insert(const_iterator pos, value_type &&value) -> iterator
Inserts an element value at the position before pos in the container.
Definition: dynamic_array.hpp:1474
constexpr auto empty() const noexcept -> bool
Check if the basic_dynamic_array is empty.
Definition: dynamic_array.hpp:1409
Definition: strong_type.hpp:12
Definition: dynamic_array.hpp:51