General Utility Library for C++17 26.5.0
SmallVector.h
Go to the documentation of this file.
1
26#ifndef GUL17_SMALLVECTOR_H_
27#define GUL17_SMALLVECTOR_H_
28
29#include <algorithm>
30#include <array>
31#include <cstddef>
32#include <cstdint>
33#include <initializer_list>
34#include <iterator>
35#include <limits>
36#include <memory>
37#include <new>
38#include <stdexcept>
39#include <type_traits>
40#include <utility>
41
42#include "gul17/cat.h"
43#include "gul17/finalizer.h"
44#include "gul17/internal.h"
45
46namespace gul17 {
47
276template <typename ElementT, size_t in_capacity>
278{
279public:
285 using SizeType = std::uint32_t;
289 using DifferenceType = std::ptrdiff_t;
297 using ConstReference = const ValueType&;
305 using ConstIterator = const ValueType*;
309 using ReverseIterator = std::reverse_iterator<Iterator>;
313 using ConstReverseIterator = std::reverse_iterator<ConstIterator>;
316
326
334 {
335 static_assert(std::is_default_constructible<ValueType>::value,
336 "SmallVector: Element type is not default-constructible");
337
339 for (SizeType i = 0u; i != num_elements; ++i)
340 ::new(static_cast<void*>(data() + i)) ValueType{};
341 size_ = num_elements;
342 }
343
352 {
353 fill_empty_vector_with_copied_value(num_elements, value);
354 }
355
372 template<class InputIterator,
373 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
375 {
376 fill_empty_vector_with_copied_range(first, last);
377 }
378
388 noexcept(std::is_nothrow_copy_constructible<ValueType>::value)
389 {
390 static_assert(std::is_copy_constructible<ValueType>::value == true,
391 "SmallVector: Element type is not copy-constructible");
392 fill_empty_vector_with_copied_range(other.cbegin(), other.cend());
393 }
394
411 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
412 {
413 move_or_copy_all_elements_from(std::move(other));
414 }
415
423 SmallVector(std::initializer_list<ValueType> init)
424 {
425 fill_empty_vector_with_copied_range(init.begin(), init.end());
426 }
427
430 {
431 clear();
432 if (is_storage_allocated())
433 deallocate_space_for_elements(data_ptr_);
434 }
435
444 {
445 clear();
446 fill_empty_vector_with_copied_value(num_elements, value);
447 }
448
468 template<class InputIterator,
469 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
471 {
472 clear();
473 fill_empty_vector_with_copied_range(first, last);
474 }
475
483 void assign(std::initializer_list<ValueType> init)
484 {
485 const auto num_elements = static_cast<SizeType>(init.size());
486
487 clear();
489 std::uninitialized_copy(init.begin(), init.end(), data());
490 size_ = num_elements;
491 }
492
498 {
499 if (idx >= size_)
500 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
501 return *(data() + idx);
502 }
503
505 constexpr ConstReference at(SizeType idx) const
506 {
507 if (idx >= size_)
508 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
509 return *(data() + idx);
510 }
511
517 {
518 return *(data_end() - 1);
519 }
520
526 {
527 return *(data_end() - 1);
528 }
529
535 {
536 return data();
537 }
538
544 {
545 return data();
546 }
547
552 constexpr SizeType capacity() const noexcept { return capacity_; }
553
559 {
560 return begin();
561 }
562
568 {
569 return end();
570 }
571
577 {
578 destroy_range(data(), data_end());
579 size_ = 0;
580 }
581
589 {
590 return std::make_reverse_iterator(end());
591 }
592
600 {
601 return std::make_reverse_iterator(begin());
602 }
603
609 {
610 return data_ptr_;
611 }
612
617 constexpr const ValueType* data() const noexcept
618 {
619 return data_ptr_;
620 }
621
647 template <typename... ArgumentTypes>
649 {
650 if (pos == cend())
651 {
652 emplace_back(std::forward<ArgumentTypes>(arguments)...);
653 return data_end() - 1;
654 }
655
656 ValueType v(std::forward<ArgumentTypes>(arguments)...);
657
658 return insert_single_value(pos, std::move(v));
659 }
660
678 template <typename... ArgumentTypes>
680 {
681 if (size_ == capacity_)
682 grow();
683
684 ::new(static_cast<void*>(data_end()))
685 ValueType(std::forward<ArgumentTypes>(arguments)...);
686
687 ++size_;
688
689 return back();
690 }
691
693 constexpr bool empty() const noexcept { return size_ == 0u; }
694
700 {
701 return data_end();
702 }
703
709 {
710 return data_end();
711 }
712
725 {
726 return erase(pos, pos + 1);
727 }
728
743 {
744 auto range_begin = const_cast<Iterator>(first);
745 auto range_end = const_cast<Iterator>(last);
747
748 std::move(range_end, end(), range_begin);
749 destroy_range(end() - num_elements, end());
750
751 size_ -= static_cast<SizeType>(num_elements);
752
753 return range_begin;
754 }
755
761 {
762 return *data();
763 }
764
770 {
771 return *data();
772 }
773
779
790 {
791 return insert_single_value(pos, value);
792 }
793
804 {
805 return insert_single_value(pos, std::move(value));
806 }
807
818 {
819 const auto idx = static_cast<SizeType>(pos - begin());
820 if (num_elements < 1)
821 return begin() + idx;
822
823 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
825
826 // Copy-assign to moved-from elements
827 std::fill_n(insert_pos, num_assignable, value);
828
829 // Copy the remaining values into uninitialized cells
830 copy_value_into_uninitialized_cells(size_, num_elements - num_assignable, value);
831
832 size_ += num_elements;
833
834 return insert_pos;
835 }
836
856 template<class InputIterator,
857 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
859 {
860 const auto idx = static_cast<SizeType>(pos - begin());
861 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
862 if (num_elements < 1)
863 return begin() + idx;
864
865 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
867
868 // Copy-assign to moved-from elements
869 std::copy_n(first, num_assignable, insert_pos);
870
871 // Copy the remaining values into uninitialized cells
872 copy_range_into_uninitialized_cells(size_, first + num_assignable, last);
873
874 size_ += num_elements;
875
876 return insert_pos;
877 }
878
892 Iterator insert(ConstIterator pos, std::initializer_list<ValueType> init)
893 {
894 return insert(pos, init.begin(), init.end());
895 }
896
904 {
905 return std::numeric_limits<SizeType>::max();
906 }
907
916 noexcept(std::is_nothrow_copy_assignable<ValueType>::value)
917 {
918 if (&other != this)
919 {
920 clear();
921 reserve(other.size());
922 std::uninitialized_copy(other.cbegin(), other.cend(), data());
923 size_ = other.size();
924 }
925
926 return *this;
927 }
928
943 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
944 {
945 if (&other != this)
946 {
947 clear();
948 if (is_storage_allocated())
949 deallocate_space_for_elements(data_ptr_);
950 move_or_copy_all_elements_from(std::move(other));
951 }
952
953 return *this;
954 }
955
960 SmallVector& operator=(std::initializer_list<ValueType> init)
961 {
962 assign(init);
963 return *this;
964 }
965
973 friend bool operator==(const SmallVector& lhs, const SmallVector& rhs)
974 {
975 return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
976 }
977
985 friend bool operator!=(const SmallVector& lhs, const SmallVector& rhs)
986 {
987 return not (lhs == rhs);
988 }
989
992 {
993 return *(data() + idx);
994 }
995
998 {
999 return *(data() + idx);
1000 }
1001
1007 {
1008 --size_;
1009 auto p = data_end();
1010 p->~ValueType();
1011 }
1012
1023 {
1024 if (size_ == capacity_)
1025 grow();
1026
1027 ::new(static_cast<void*>(data_end())) ValueType(value);
1028
1029 ++size_;
1030 }
1031
1041 {
1042 if (size_ == capacity_)
1043 grow();
1044
1045 ::new(static_cast<void*>(data_end())) ValueType(std::move(value));
1046
1047 ++size_;
1048 }
1049
1057 {
1058 return std::make_reverse_iterator(end());
1059 }
1060
1067 {
1068 return std::make_reverse_iterator(begin());
1069 }
1070
1080 {
1081 if (new_capacity <= capacity_)
1082 return;
1083
1084 // Allocate aligned memory for the new "outer" capacity.
1085 auto* new_data = allocate_space_for_elements(new_capacity);
1086 auto _ = finally([&new_data]() { deallocate_space_for_elements(new_data); });
1087
1088 auto* d_end = data_end();
1089 uninitialized_move_or_copy(data(), d_end, new_data);
1090 destroy_range(data(), d_end);
1091
1092 if (is_storage_allocated())
1093 deallocate_space_for_elements(data_ptr_);
1094
1095 data_ptr_ = new_data;
1096 new_data = nullptr;
1097 capacity_ = new_capacity;
1098 }
1099
1116 {
1117 static_assert(std::is_default_constructible<ValueType>::value,
1118 "SmallVector: For using resize(), element type must be default-constructible");
1119
1120 if (num_elements < size_)
1121 {
1122 destroy_range(data() + num_elements, data_end());
1123 }
1124 else if (num_elements > size_)
1125 {
1127 fill_uninitialized_cells_with_default_constructed_elements(size_,
1128 num_elements - size_);
1129 }
1130
1131 size_ = num_elements;
1132 }
1133
1146 {
1147 if (num_elements < size_)
1148 {
1149 destroy_range(data() + num_elements, data_end());
1150 }
1151 else if (num_elements > size_)
1152 {
1154 copy_value_into_uninitialized_cells(size_, num_elements - size_, element);
1155 }
1156
1157 size_ = num_elements;
1158 }
1159
1165 {
1166 const SizeType new_capacity = std::max(inner_capacity(), size_);
1167
1168 // No shrinking required?
1169 if (new_capacity == capacity_)
1170 return;
1171
1174 auto _ = finally([&allocation]() { deallocate_space_for_elements(allocation); });
1175
1177 {
1178 new_data = get_internal_array_pointer();
1179 }
1180 else
1181 {
1182 allocation = allocate_space_for_elements(new_capacity);
1184 }
1185
1186 auto* d_end = data_end();
1187 uninitialized_move_or_copy(data(), d_end, new_data);
1188 destroy_range(data(), d_end);
1189
1190 if (is_storage_allocated())
1191 deallocate_space_for_elements(data_ptr_);
1192
1193 data_ptr_ = new_data;
1194 capacity_ = new_capacity;
1195 allocation = nullptr; // Avoid deallocation by the "finally" guard
1196 }
1197
1199 constexpr SizeType size() const noexcept { return size_; }
1200
1209 {
1210 if (is_storage_allocated())
1211 {
1212 if (other.is_storage_allocated())
1213 swap_heap_with_heap(*this, other);
1214 else
1215 swap_heap_with_internal(*this, other);
1216 }
1217 else
1218 {
1219 if (other.is_storage_allocated())
1220 swap_heap_with_internal(other, *this);
1221 else
1222 swap_internal_with_internal(*this, other);
1223 }
1224 }
1225
1226private:
1231 alignas(ValueType)
1232 std::array<std::byte, in_capacity * sizeof(ValueType)> internal_array_;
1233
1235 ValueType* data_ptr_{ get_internal_array_pointer() };
1236
1239 SizeType capacity_{ in_capacity };
1241 SizeType size_{ 0u };
1242
1247 static ValueType* allocate_space_for_elements(std::size_t num_elements)
1248 {
1249 return static_cast<ValueType*>(
1250 ::operator new[](num_elements * sizeof(ValueType),
1251 std::align_val_t{ alignof(ValueType) }));
1252 }
1253
1266 template<class InputIterator>
1267 void copy_range_into_uninitialized_cells(SizeType pos, InputIterator first,
1268 InputIterator last)
1269 {
1270 auto data_ptr = data() + pos;
1271
1272 try
1273 {
1274 for (auto it = first; it != last; ++it)
1275 {
1276 ::new(static_cast<void*>(data_ptr)) ValueType{ *it };
1277 ++data_ptr;
1278 }
1279 }
1280 catch (...)
1281 {
1282 for (auto p = data() + pos; p != data_ptr; ++p)
1283 p->~ValueType();
1284
1285 throw;
1286 }
1287 }
1288
1295 void copy_value_into_uninitialized_cells(SizeType pos, SizeType num_elements,
1296 const ValueType& value)
1297 {
1298 const auto start_ptr = data() + pos;
1299 const auto end_ptr = start_ptr + num_elements;
1300 for (auto p = start_ptr; p != end_ptr; ++p)
1301 ::new(static_cast<void*>(p)) ValueType(value);
1302 }
1303
1305 constexpr ValueType* data_end() noexcept
1306 {
1307 return data_ptr_ + size_;
1308 }
1309
1311 constexpr const ValueType* data_end() const noexcept
1312 {
1313 return data_ptr_ + size_;
1314 }
1315
1317 static void deallocate_space_for_elements(ValueType* ptr) noexcept
1318 {
1319 ::operator delete[](ptr, std::align_val_t{ alignof(ValueType) });
1320 }
1321
1330 static void destroy_range(Iterator it_start, Iterator it_end) noexcept
1331 {
1332 for (auto it = it_start; it != it_end; ++it)
1333 it->~ValueType();
1334 }
1335
1350 template<typename InputIterator>
1351 void fill_empty_vector_with_copied_range(InputIterator first, InputIterator last)
1352 {
1353 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
1354
1356 copy_range_into_uninitialized_cells(0u, first, last);
1357 size_ = num_elements;
1358 }
1359
1368 void fill_empty_vector_with_copied_value(SizeType num_elements, const ValueType& value)
1369 {
1371 copy_value_into_uninitialized_cells(0u, num_elements, value);
1372 size_ = num_elements;
1373 }
1374
1383 void fill_uninitialized_cells_with_default_constructed_elements(SizeType pos,
1385 {
1386 const auto start_ptr = data() + pos;
1387 const auto end_ptr = start_ptr + num_elements;
1388 auto ptr = start_ptr;
1389
1390 try
1391 {
1392 for (; ptr != end_ptr; ++ptr)
1393 ::new(static_cast<void*>(ptr)) ValueType{};
1394 }
1395 catch (...)
1396 {
1397 destroy_range(start_ptr, ptr);
1398 throw;
1399 }
1400 }
1401
1403 const ValueType* get_internal_array_pointer() const noexcept
1404 {
1405 return reinterpret_cast<const ValueType*>(internal_array_.data());
1406 }
1407
1409 ValueType* get_internal_array_pointer() noexcept
1410 {
1411 return reinterpret_cast<ValueType*>(internal_array_.data());
1412 }
1413
1423 void grow()
1424 {
1425 const auto remaining_space = std::numeric_limits<SizeType>::max() - capacity_;
1426
1427 if (remaining_space == 0u)
1428 throw std::length_error("Max. capacity reached");
1429
1430 SizeType increase = capacity_ / 2u;
1433 else if (increase == 0u)
1434 increase = 1u;
1435
1436 reserve(capacity_ + increase);
1437 }
1438
1440 template <typename T>
1441 Iterator insert_single_value(ConstIterator pos, T&& value)
1442 {
1443 if (pos == end())
1444 {
1445 push_back(std::forward<T>(value));
1446 return begin() + size_ - 1;
1447 }
1448
1449 const auto idx = static_cast<SizeType>(pos - begin());
1450
1451 if (size_ == capacity_)
1452 grow();
1453
1455
1456 auto data_ptr = data();
1457
1458 // Construct new back() element by moving from the old back()
1459 ::new(static_cast<void*>(data_ptr + size_)) ValueType(std::move(*(data_ptr + size_ - 1)));
1460
1461 std::move_backward(insert_pos, data_ptr + size_ - 1, data_ptr + size_);
1462 ++size_;
1463
1464 *insert_pos = std::forward<T>(value);
1465
1466 return insert_pos;
1467 }
1468
1470 bool is_storage_allocated() const noexcept
1471 {
1472 return data_ptr_ != get_internal_array_pointer();
1473 }
1474
1485 SizeType make_space_at_idx_for_n_elements(SizeType idx, SizeType num_elements)
1486 {
1487 const auto new_size = size_ + num_elements;
1488
1489 if (new_size > capacity_)
1491
1492 auto data_ptr = data();
1493
1494 // We have a total number of elements that need to be shifted backwards,
1495 // of which some need to be move-initialized at the end of the vector
1496 // and some simply need to be moved from one element to another.
1497 const SizeType num_shifted = size_ - idx;
1500
1501 // Move-initialize elements in uninitialized space at the back of the container
1502 const auto from_ptr = data_ptr + size_ - num_move_initialized;
1503 const auto to_ptr = from_ptr + num_elements;
1504 for (SizeType i = 0; i != num_move_initialized; ++i)
1505 ::new(static_cast<void*>(to_ptr + i)) ValueType(std::move(*(from_ptr + i)));
1506
1507 // Move elements backwards within old vector size
1508 std::move_backward(data_ptr + idx, data_ptr + idx + num_moved, to_ptr);
1509
1510 return num_move_initialized;
1511 }
1512
1533 void move_or_copy_all_elements_from(SmallVector&& other)
1534 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
1535 {
1536 // Can we simply steal the complete allocated storage?
1537 if (other.is_storage_allocated())
1538 {
1539 data_ptr_ = std::exchange(other.data_ptr_, other.get_internal_array_pointer());
1540 capacity_ = std::exchange(other.capacity_, other.inner_capacity());
1541 size_ = std::exchange(other.size_, 0u);
1542 }
1543 else // otherwise fall back to moving (or at least copying) all elements
1544 {
1545 data_ptr_ = get_internal_array_pointer();
1546 capacity_ = in_capacity;
1547 uninitialized_move_or_copy(other.begin(), other.end(), data());
1548 size_ = other.size();
1549 other.clear();
1550 }
1551 }
1552
1558 static void swap_heap_with_heap(SmallVector &a, SmallVector &b) noexcept
1559 {
1560 std::swap(a.data_ptr_, b.data_ptr_);
1561 std::swap(a.capacity_, b.capacity_);
1562 std::swap(a.size_, b.size_);
1563 }
1564
1571 static void swap_heap_with_internal(SmallVector &a, SmallVector &b)
1572 {
1573 uninitialized_move_or_copy(b.begin(), b.end(), a.get_internal_array_pointer());
1574 destroy_range(b.begin(), b.end());
1575
1576 b.data_ptr_ = std::exchange(a.data_ptr_, a.get_internal_array_pointer());
1577
1578 std::swap(a.capacity_, b.capacity_);
1579 std::swap(a.size_, b.size_);
1580 }
1581
1587 static void swap_internal_with_internal(SmallVector &a, SmallVector &b)
1588 {
1589 if (a.size_ <= b.size_)
1590 {
1591 for (SmallVector::SizeType i = 0; i != a.size_; ++i)
1592 std::swap(a.data()[i], b.data()[i]);
1593
1594 uninitialized_move_or_copy(b.begin() + a.size_, b.end(), a.begin() + a.size_);
1595 destroy_range(b.begin() + a.size_, b.end());
1596 }
1597 else
1598 {
1599 for (SizeType i = 0; i != b.size_; ++i)
1600 std::swap(a.data()[i], b.data()[i]);
1601
1602 uninitialized_move_or_copy(a.begin() + b.size_, a.end(), b.begin() + b.size_);
1603 destroy_range(a.begin() + b.size_, a.end());
1604 }
1605
1606 std::swap(a.size_, b.size_);
1607 }
1608
1613 template <typename T>
1614 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value>
1615 uninitialized_move(T* src_begin, T* src_end, T* dest_begin)
1616 {
1617 auto src = src_begin;
1618 auto dest = dest_begin;
1619
1620 try
1621 {
1622 while (src != src_end)
1623 {
1624 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1625 ++src;
1626 ++dest;
1627 }
1628 }
1629 catch (...)
1630 {
1631 for (auto p = dest_begin; p != dest; ++p)
1632 p->~ValueType();
1633
1634 throw;
1635 }
1636 }
1637
1642 template <typename T>
1643 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1644 uninitialized_move(T* src_begin, T* src_end, T* dest_begin) noexcept
1645 {
1646 auto src = src_begin;
1647 auto dest = dest_begin;
1648
1649 while (src != src_end)
1650 {
1651 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1652 ++src;
1653 ++dest;
1654 }
1655 }
1656
1659 template <typename T>
1660 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1661 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin) noexcept
1662 {
1663 uninitialized_move(src_begin, src_end, dest_begin);
1664 }
1665
1668 template <typename T>
1669 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value and
1670 std::is_copy_constructible<T>::value>
1671 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1672 {
1673 std::uninitialized_copy(src_begin, src_end, dest_begin);
1674 }
1675
1678 template <typename T>
1679 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value
1680 and not std::is_copy_constructible<T>::value>
1681 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1682 {
1683 uninitialized_move(src_begin, src_end, dest_begin);
1684 }
1685};
1686
1687
1695template<typename ElementT, size_t in_capacity>
1700
1702
1703} // namespace gul17
1704
1705#endif
1706
1707// vi:ts=4:sw=4:sts=4:et
Declaration of the overload set for cat() and of the associated class ConvertingStringView.
A resizable container with contiguous storage that can hold a specified number of elements without al...
Definition SmallVector.h:278
constexpr Iterator begin() noexcept
Return an iterator to the first element of the vector.
Definition SmallVector.h:534
void assign(SizeType num_elements, const ValueType &value)
Fill the vector with a certain number of copies of the given value after clearing all previous conten...
Definition SmallVector.h:443
Iterator emplace(ConstIterator pos, ArgumentTypes &&... arguments)
Construct an additional element at an arbitrary position in the vector.
Definition SmallVector.h:648
SmallVector & operator=(const SmallVector &other) noexcept(std::is_nothrow_copy_assignable< ValueType >::value)
Copy assignment operator: Copy all elements from another SmallVector after clearing all previous cont...
Definition SmallVector.h:915
std::reverse_iterator< ConstIterator > ConstReverseIterator
Iterator to a const element in reversed container.
Definition SmallVector.h:313
SmallVector(std::initializer_list< ValueType > init)
Construct a SmallVector that is filled with copies of the elements from a given initializer list.
Definition SmallVector.h:423
constexpr Reference operator[](SizeType idx)
Return a reference to the element at the specified index.
Definition SmallVector.h:991
constexpr ConstIterator cbegin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:558
friend bool operator!=(const SmallVector &lhs, const SmallVector &rhs)
Inequality operator: Return true if both vectors have a different size() or at least one different el...
Definition SmallVector.h:985
void clear() noexcept
Erase all elements from the container without changing its capacity.
Definition SmallVector.h:576
SmallVector(SizeType num_elements, const ValueType &value)
Construct a SmallVector that is filled with a certain number of copies of the given value.
Definition SmallVector.h:351
ReverseIterator rbegin() noexcept
Return a reverse iterator to the first element of the reversed vector (which is the last element of t...
Definition SmallVector.h:1056
constexpr Reference at(SizeType idx)
Return a reference to the element at the specified index with bounds-checking.
Definition SmallVector.h:497
Reference reference
Reference to an element.
Definition SmallVector.h:295
constexpr ConstReference operator[](SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:997
constexpr Reference back() noexcept
Return a reference to the last element in the vector.
Definition SmallVector.h:516
ValueType value_type
Type of the elements in the underlying container.
Definition SmallVector.h:283
Iterator insert(ConstIterator pos, SizeType num_elements, const ValueType &value)
Insert a number of copies of the given value before the indicated position.
Definition SmallVector.h:817
ConstReverseIterator crbegin() noexcept
Return a const reverse iterator to the first element of the reversed vector (which is the last elemen...
Definition SmallVector.h:588
friend bool operator==(const SmallVector &lhs, const SmallVector &rhs)
Equality operator: Return true if both vectors have the same size() and the same elements.
Definition SmallVector.h:973
void assign(InputIterator first, InputIterator last)
Fill the vector with copies of elements from the given range.
Definition SmallVector.h:470
ValueType * Iterator
Iterator to an element.
Definition SmallVector.h:301
void assign(std::initializer_list< ValueType > init)
Assign the elements of an initializer list to this vector after clearing all previous contents.
Definition SmallVector.h:483
Iterator insert(ConstIterator pos, std::initializer_list< ValueType > init)
Insert elements from an initializer list before the indicated position.
Definition SmallVector.h:892
void shrink_to_fit()
Reduce the capacity as far as possible while retaining all stored elements.
Definition SmallVector.h:1164
ElementT ValueType
Type of the elements in the underlying container.
Definition SmallVector.h:281
constexpr ConstIterator cend() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:567
const ValueType & ConstReference
Reference to a const element.
Definition SmallVector.h:297
Iterator iterator
Iterator to an element.
Definition SmallVector.h:303
SmallVector(SmallVector &&other) noexcept(std::is_nothrow_move_constructible< ValueType >::value)
Move constructor: Create a SmallVector from the contents of another one with the same inner capacity ...
Definition SmallVector.h:410
~SmallVector()
Destructor: Destroys all stored elements and frees all allocated memory.
Definition SmallVector.h:429
void swap(SmallVector &other)
Exchange the contents of this SmallVector with those of another one.
Definition SmallVector.h:1208
void reserve(SizeType new_capacity)
Increase the capacity of the vector to the specified size.
Definition SmallVector.h:1079
std::ptrdiff_t DifferenceType
Signed integer type for the difference of two iterators.
Definition SmallVector.h:289
constexpr ConstReference front() const noexcept
Return a const reference to the first element in the vector.
Definition SmallVector.h:769
constexpr ConstIterator begin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:543
SmallVector() noexcept=default
Construct an empty SmallVector.
ConstReference const_reference
Reference to a const element.
Definition SmallVector.h:299
Iterator erase(ConstIterator pos)
Erase a single element from the vector, moving elements behind it forward.
Definition SmallVector.h:724
constexpr ValueType * data() noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:608
SmallVector & operator=(std::initializer_list< ValueType > init)
Assign the elements of an initializer list to this vector after clearing all previous contents.
Definition SmallVector.h:960
SmallVector(InputIterator first, InputIterator last)
Construct a SmallVector that is filled with copies of elements from the given range.
Definition SmallVector.h:374
ReverseIterator rend() noexcept
Return a reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:1066
ValueType & Reference
Reference to an element.
Definition SmallVector.h:293
std::uint32_t SizeType
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:285
SizeType size_type
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:287
constexpr ConstReference back() const noexcept
Return a const reference to the last element in the vector.
Definition SmallVector.h:525
constexpr Reference front() noexcept
Return a reference to the first element in the vector.
Definition SmallVector.h:760
constexpr const ValueType * data() const noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:617
Iterator insert(ConstIterator pos, ValueType &&value)
Insert a single element before the indicated position.
Definition SmallVector.h:803
SmallVector(const SmallVector &other) noexcept(std::is_nothrow_copy_constructible< ValueType >::value)
Create a copy of another SmallVector with the same inner capacity.
Definition SmallVector.h:387
constexpr bool empty() const noexcept
Determine if the vector is empty.
Definition SmallVector.h:693
Iterator insert(ConstIterator pos, const ValueType &value)
Insert a single element before the indicated position.
Definition SmallVector.h:789
void resize(SizeType num_elements)
Change the number of elements in the container.
Definition SmallVector.h:1115
constexpr SizeType capacity() const noexcept
Return the number of elements that can currently be stored in this vector without having to allocate ...
Definition SmallVector.h:552
SmallVector & operator=(SmallVector &&other) noexcept(std::is_nothrow_move_constructible< ValueType >::value)
Move assignment operator: Assign all of the elements from another vector to this one using move seman...
Definition SmallVector.h:942
constexpr ConstIterator end() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:708
constexpr SizeType inner_capacity() const noexcept
Return the number of elements this SmallVector can hold internally without having to allocate storage...
Definition SmallVector.h:778
Reference emplace_back(ArgumentTypes &&... arguments)
Construct an additional element at the end of the buffer.
Definition SmallVector.h:679
void push_back(ValueType &&value)
Move one element to the end of the buffer.
Definition SmallVector.h:1040
Iterator erase(ConstIterator first, ConstIterator last)
Erase a range of elements from the vector, moving elements behind the range forward.
Definition SmallVector.h:742
Iterator insert(ConstIterator pos, InputIterator first, InputIterator last)
Insert a range of values before the indicated position.
Definition SmallVector.h:858
constexpr SizeType max_size() const noexcept
Return the maximum number of elements that this vector can theoretically hold.
Definition SmallVector.h:903
ConstReverseIterator const_reverse_iterator
Iterator to a const element in reversed container.
Definition SmallVector.h:315
ConstIterator const_iterator
Iterator to a const element.
Definition SmallVector.h:307
constexpr ConstReference at(SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:505
void push_back(const ValueType &value)
Copy one element to the end of the buffer.
Definition SmallVector.h:1022
void resize(SizeType num_elements, const ValueType &element)
Change the number of elements in the container.
Definition SmallVector.h:1145
constexpr SizeType size() const noexcept
Return the number of elements that are currently stored.
Definition SmallVector.h:1199
void pop_back()
Remove the last element from the vector.
Definition SmallVector.h:1006
DifferenceType difference_type
Signed integer type for the difference of two iterators.
Definition SmallVector.h:291
ReverseIterator reverse_iterator
Iterator to an element in reversed container.
Definition SmallVector.h:311
std::reverse_iterator< Iterator > ReverseIterator
Iterator to an element in reversed container.
Definition SmallVector.h:309
ConstReverseIterator crend() noexcept
Return a const reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:599
const ValueType * ConstIterator
Iterator to a const element.
Definition SmallVector.h:305
constexpr Iterator end() noexcept
Return an iterator pointing past the last element of the vector.
Definition SmallVector.h:699
Implementation of FinalAction and finally().
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition SmallVector.h:1696
auto constexpr bit_set(unsigned bit) noexcept -> ReturnT
Set a bit in an integral type.
Definition bit_manip.h:124
std::string cat()
Efficiently concatenate an arbitrary number of strings and numbers.
Definition cat.h:100
Definition of macros used internally by GUL.
Namespace gul17 contains all functions and classes of the General Utility Library.
Definition doxygen.h:29