General Utility Library for C++17 25.7.0
SmallVector.h
Go to the documentation of this file.
1
23#ifndef GUL17_SMALLVECTOR_H_
24#define GUL17_SMALLVECTOR_H_
25
26#include <algorithm>
27#include <array>
28#include <cstdint>
29#include <initializer_list>
30#include <iterator>
31#include <limits>
32#include <memory>
33#include <stdexcept>
34#include <type_traits>
35
36#include "gul17/internal.h"
37#include "gul17/cat.h"
38
39namespace gul17 {
40
269template <typename ElementT, size_t in_capacity>
271{
272public:
278 using SizeType = std::uint32_t;
282 using DifferenceType = std::ptrdiff_t;
290 using ConstReference = const ValueType&;
298 using ConstIterator = const ValueType*;
302 using ReverseIterator = std::reverse_iterator<Iterator>;
306 using ConstReverseIterator = std::reverse_iterator<ConstIterator>;
309
319
327 {
328 static_assert(std::is_default_constructible<ValueType>::value,
329 "SmallVector: Element type is not default-constructible");
330
332 for (SizeType i = 0u; i != num_elements; ++i)
333 ::new(static_cast<void*>(data() + i)) ValueType{};
334 size_ = num_elements;
335 }
336
345 {
346 fill_empty_vector_with_copied_value(num_elements, value);
347 }
348
365 template<class InputIterator,
366 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
368 {
369 fill_empty_vector_with_copied_range(first, last);
370 }
371
381 noexcept(std::is_nothrow_copy_constructible<ValueType>::value)
382 {
383 static_assert(std::is_copy_constructible<ValueType>::value == true,
384 "SmallVector: Element type is not copy-constructible");
385 fill_empty_vector_with_copied_range(other.cbegin(), other.cend());
386 }
387
404 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
405 {
406 move_or_copy_all_elements_from(std::move(other));
407 }
408
416 SmallVector(std::initializer_list<ValueType> init)
417 {
418 fill_empty_vector_with_copied_range(init.begin(), init.end());
419 }
420
423 {
424 clear();
425
426 if (is_storage_allocated())
427 delete[] data_ptr_;
428 }
429
438 {
439 clear();
440 fill_empty_vector_with_copied_value(num_elements, value);
441 }
442
462 template<class InputIterator,
463 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
465 {
466 clear();
467 fill_empty_vector_with_copied_range(first, last);
468 }
469
477 void assign(std::initializer_list<ValueType> init)
478 {
479 const auto num_elements = static_cast<SizeType>(init.size());
480
481 clear();
483 std::uninitialized_copy(init.begin(), init.end(), data());
484 size_ = num_elements;
485 }
486
492 {
493 if (idx >= size_)
494 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
495 return *(data() + idx);
496 }
497
499 constexpr ConstReference at(SizeType idx) const
500 {
501 if (idx >= size_)
502 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
503 return *(data() + idx);
504 }
505
511 {
512 return *(data_end() - 1);
513 }
514
520 {
521 return *(data_end() - 1);
522 }
523
529 {
530 return data();
531 }
532
538 {
539 return data();
540 }
541
546 constexpr SizeType capacity() const noexcept { return capacity_; }
547
553 {
554 return begin();
555 }
556
562 {
563 return end();
564 }
565
571 {
572 destroy_range(data(), data_end());
573 size_ = 0;
574 }
575
583 {
584 return std::make_reverse_iterator(end());
585 }
586
594 {
595 return std::make_reverse_iterator(begin());
596 }
597
603 {
604 return reinterpret_cast<ValueType*>(data_ptr_);
605 }
606
611 constexpr const ValueType* data() const noexcept
612 {
613 return reinterpret_cast<const ValueType*>(data_ptr_);
614 }
615
641 template <typename... ArgumentTypes>
643 {
644 if (pos == cend())
645 {
646 emplace_back(std::forward<ArgumentTypes>(arguments)...);
647 return data_end() - 1;
648 }
649
650 ValueType v(std::forward<ArgumentTypes>(arguments)...);
651
652 return insert_single_value(pos, std::move(v));
653 }
654
672 template <typename... ArgumentTypes>
674 {
675 if (size_ == capacity_)
676 grow();
677
678 ::new(static_cast<void*>(data_end()))
679 ValueType(std::forward<ArgumentTypes>(arguments)...);
680
681 ++size_;
682
683 return back();
684 }
685
687 constexpr bool empty() const noexcept { return size_ == 0u; }
688
694 {
695 return data_end();
696 }
697
703 {
704 return data_end();
705 }
706
719 {
720 return erase(pos, pos + 1);
721 }
722
737 {
738 auto range_begin = const_cast<Iterator>(first);
739 auto range_end = const_cast<Iterator>(last);
741
742 std::move(range_end, end(), range_begin);
743 destroy_range(end() - num_elements, end());
744
745 size_ -= static_cast<SizeType>(num_elements);
746
747 return range_begin;
748 }
749
755 {
756 return *data();
757 }
758
764 {
765 return *data();
766 }
767
773
784 {
785 return insert_single_value(pos, value);
786 }
787
798 {
799 return insert_single_value(pos, std::move(value));
800 }
801
812 {
813 const auto idx = static_cast<SizeType>(pos - begin());
814 if (num_elements < 1)
815 return begin() + idx;
816
817 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
819
820 // Copy-assign to moved-from elements
821 std::fill_n(insert_pos, num_assignable, value);
822
823 // Copy the remaining values into uninitialized cells
824 copy_value_into_uninitialized_cells(size_, num_elements - num_assignable, value);
825
826 size_ += num_elements;
827
828 return insert_pos;
829 }
830
850 template<class InputIterator,
851 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
853 {
854 const auto idx = static_cast<SizeType>(pos - begin());
855 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
856 if (num_elements < 1)
857 return begin() + idx;
858
859 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
861
862 // Copy-assign to moved-from elements
863 std::copy_n(first, num_assignable, insert_pos);
864
865 // Copy the remaining values into uninitialized cells
866 copy_range_into_uninitialized_cells(size_, first + num_assignable, last);
867
868 size_ += num_elements;
869
870 return insert_pos;
871 }
872
886 Iterator insert(ConstIterator pos, std::initializer_list<ValueType> init)
887 {
888 return insert(pos, init.begin(), init.end());
889 }
890
898 {
899 return std::numeric_limits<SizeType>::max();
900 }
901
910 noexcept(std::is_nothrow_copy_assignable<ValueType>::value)
911 {
912 if (&other != this)
913 {
914 clear();
915 reserve(other.size());
916 std::uninitialized_copy(other.cbegin(), other.cend(), data());
917 size_ = other.size();
918 }
919
920 return *this;
921 }
922
937 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
938 {
939 if (&other != this)
940 {
941 clear();
942 if (is_storage_allocated())
943 delete[] data_ptr_;
944 move_or_copy_all_elements_from(std::move(other));
945 }
946
947 return *this;
948 }
949
954 SmallVector& operator=(std::initializer_list<ValueType> init)
955 {
956 assign(init);
957 return *this;
958 }
959
967 friend bool operator==(const SmallVector& lhs, const SmallVector& rhs)
968 {
969 return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
970 }
971
979 friend bool operator!=(const SmallVector& lhs, const SmallVector& rhs)
980 {
981 return not (lhs == rhs);
982 }
983
986 {
987 return *(data() + idx);
988 }
989
992 {
993 return *(data() + idx);
994 }
995
1001 {
1002 --size_;
1003 auto p = data_end();
1004 p->~ValueType();
1005 }
1006
1017 {
1018 if (size_ == capacity_)
1019 grow();
1020
1021 ::new(static_cast<void*>(data_end())) ValueType(value);
1022
1023 ++size_;
1024 }
1025
1035 {
1036 if (size_ == capacity_)
1037 grow();
1038
1039 ::new(static_cast<void*>(data_end())) ValueType(std::move(value));
1040
1041 ++size_;
1042 }
1043
1051 {
1052 return std::make_reverse_iterator(end());
1053 }
1054
1061 {
1062 return std::make_reverse_iterator(begin());
1063 }
1064
1074 {
1075 if (new_capacity <= capacity_)
1076 return;
1077
1078 auto new_data = std::make_unique<AlignedStorage[]>(new_capacity);
1079
1080 const auto d_end = data_end();
1081
1082 uninitialized_move_or_copy(data(), d_end, reinterpret_cast<ValueType*>(new_data.get()));
1083 destroy_range(data(), d_end);
1084
1085 if (is_storage_allocated())
1086 delete[] data_ptr_;
1087
1088 data_ptr_ = new_data.release();
1089 capacity_ = new_capacity;
1090 }
1091
1108 {
1109 static_assert(std::is_default_constructible<ValueType>::value,
1110 "SmallVector: For using resize(), element type must be default-constructible");
1111
1112 if (num_elements < size_)
1113 {
1114 destroy_range(data() + num_elements, data_end());
1115 }
1116 else if (num_elements > size_)
1117 {
1119 fill_uninitialized_cells_with_default_constructed_elements(size_,
1120 num_elements - size_);
1121 }
1122
1123 size_ = num_elements;
1124 }
1125
1138 {
1139 if (num_elements < size_)
1140 {
1141 destroy_range(data() + num_elements, data_end());
1142 }
1143 else if (num_elements > size_)
1144 {
1146 copy_value_into_uninitialized_cells(size_, num_elements - size_, element);
1147 }
1148
1149 size_ = num_elements;
1150 }
1151
1157 {
1158 const SizeType new_capacity = std::max(inner_capacity(), size_);
1159
1160 // No shrinking required?
1161 if (new_capacity == capacity_)
1162 return;
1163
1164 AlignedStorage* new_data;
1165 auto new_memory = std::unique_ptr<AlignedStorage[]>{};
1166
1167 if (new_capacity == inner_capacity()) {
1168 new_data = internal_array_.data();
1169 } else {
1170 new_memory = std::make_unique<AlignedStorage[]>(new_capacity);
1171 new_data = new_memory.get();
1172 }
1173
1174 const auto d_end = data_end();
1175
1176 uninitialized_move_or_copy(data(), d_end, reinterpret_cast<ValueType*>(new_data));
1177 destroy_range(data(), d_end);
1178
1179 if (is_storage_allocated())
1180 delete[] data_ptr_;
1181
1182 data_ptr_ = new_memory ? new_memory.release() : new_data;
1183 capacity_ = new_capacity;
1184 }
1185
1187 constexpr SizeType size() const noexcept { return size_; }
1188
1197 {
1198 if (is_storage_allocated())
1199 {
1200 if (other.is_storage_allocated())
1201 swap_heap_with_heap(*this, other);
1202 else
1203 swap_heap_with_internal(*this, other);
1204 }
1205 else
1206 {
1207 if (other.is_storage_allocated())
1208 swap_heap_with_internal(other, *this);
1209 else
1210 swap_internal_with_internal(*this, other);
1211 }
1212 }
1213
1214private:
1215 using AlignedStorage =
1216 typename std::aligned_storage<sizeof(ValueType), alignof(ValueType)>::type;
1217
1222 std::array<AlignedStorage, in_capacity> internal_array_;
1223
1225 AlignedStorage* data_ptr_{ internal_array_.data() };
1226
1229 SizeType capacity_{ in_capacity };
1231 SizeType size_{ 0u };
1232
1245 template<class InputIterator>
1246 void copy_range_into_uninitialized_cells(SizeType pos, InputIterator first,
1247 InputIterator last)
1248 {
1249 auto data_ptr = data() + pos;
1250
1251 try
1252 {
1253 for (auto it = first; it != last; ++it)
1254 {
1255 ::new(static_cast<void*>(data_ptr)) ValueType{ *it };
1256 ++data_ptr;
1257 }
1258 }
1259 catch (...)
1260 {
1261 for (auto p = data() + pos; p != data_ptr; ++p)
1262 p->~ValueType();
1263
1264 throw;
1265 }
1266 }
1267
1274 void copy_value_into_uninitialized_cells(SizeType pos, SizeType num_elements,
1275 const ValueType& value)
1276 {
1277 const auto start_ptr = data() + pos;
1278 const auto end_ptr = start_ptr + num_elements;
1279 for (auto p = start_ptr; p != end_ptr; ++p)
1280 ::new(static_cast<void*>(p)) ValueType(value);
1281 }
1282
1284 constexpr ValueType* data_end() noexcept
1285 {
1286 return reinterpret_cast<ValueType*>(data_ptr_) + size_;
1287 }
1288
1290 constexpr const ValueType* data_end() const noexcept
1291 {
1292 return reinterpret_cast<const ValueType*>(data_ptr_) + size_;
1293 }
1294
1303 static void destroy_range(Iterator it_start, Iterator it_end) noexcept
1304 {
1305 for (auto it = it_start; it != it_end; ++it)
1306 it->~ValueType();
1307 }
1308
1323 template<typename InputIterator>
1324 void fill_empty_vector_with_copied_range(InputIterator first, InputIterator last)
1325 {
1326 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
1327
1329 copy_range_into_uninitialized_cells(0u, first, last);
1330 size_ = num_elements;
1331 }
1332
1341 void fill_empty_vector_with_copied_value(SizeType num_elements, const ValueType& value)
1342 {
1344 copy_value_into_uninitialized_cells(0u, num_elements, value);
1345 size_ = num_elements;
1346 }
1347
1356 void fill_uninitialized_cells_with_default_constructed_elements(SizeType pos,
1358 {
1359 const auto start_ptr = data() + pos;
1360 const auto end_ptr = start_ptr + num_elements;
1361 auto ptr = start_ptr;
1362
1363 try
1364 {
1365 for (; ptr != end_ptr; ++ptr)
1366 ::new(static_cast<void*>(ptr)) ValueType{};
1367 }
1368 catch (...)
1369 {
1370 destroy_range(start_ptr, ptr);
1371 throw;
1372 }
1373 }
1374
1384 void grow()
1385 {
1386 const auto remaining_space = std::numeric_limits<SizeType>::max() - capacity_;
1387
1388 if (remaining_space == 0u)
1389 throw std::length_error("Max. capacity reached");
1390
1391 SizeType increase = capacity_ / 2u;
1394 else if (increase == 0u)
1395 increase = 1u;
1396
1397 reserve(capacity_ + increase);
1398 }
1399
1401 template <typename T>
1402 Iterator insert_single_value(ConstIterator pos, T&& value)
1403 {
1404 if (pos == end())
1405 {
1406 push_back(std::forward<T>(value));
1407 return begin() + size_ - 1;
1408 }
1409
1410 const auto idx = static_cast<SizeType>(pos - begin());
1411
1412 if (size_ == capacity_)
1413 grow();
1414
1416
1417 auto data_ptr = data();
1418
1419 // Construct new back() element by moving from the old back()
1420 ::new(static_cast<void*>(data_ptr + size_)) ValueType(std::move(*(data_ptr + size_ - 1)));
1421
1422 std::move_backward(insert_pos, data_ptr + size_ - 1, data_ptr + size_);
1423 ++size_;
1424
1425 *insert_pos = std::forward<T>(value);
1426
1427 return insert_pos;
1428 }
1429
1431 bool is_storage_allocated() const noexcept
1432 {
1433 return data_ptr_ != internal_array_.data();
1434 }
1435
1446 SizeType make_space_at_idx_for_n_elements(SizeType idx, SizeType num_elements)
1447 {
1448 const auto new_size = size_ + num_elements;
1449
1450 if (new_size > capacity_)
1452
1453 auto data_ptr = data();
1454
1455 // We have a total number of elements that need to be shifted backwards,
1456 // of which some need to be move-initialized at the end of the vector
1457 // and some simply need to be moved from one element to another.
1458 const SizeType num_shifted = size_ - idx;
1461
1462 // Move-initialize elements in uninitialized space at the back of the container
1463 const auto from_ptr = data_ptr + size_ - num_move_initialized;
1464 const auto to_ptr = from_ptr + num_elements;
1465 for (SizeType i = 0; i != num_move_initialized; ++i)
1466 ::new(static_cast<void*>(to_ptr + i)) ValueType(std::move(*(from_ptr + i)));
1467
1468 // Move elements backwards within old vector size
1469 std::move_backward(data_ptr + idx, data_ptr + idx + num_moved, to_ptr);
1470
1471 return num_move_initialized;
1472 }
1473
1492 void move_or_copy_all_elements_from(SmallVector&& other)
1493 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
1494 {
1495 // Can we simply steal the complete allocated storage?
1496 if (other.is_storage_allocated())
1497 {
1498 data_ptr_ = other.data_ptr_; other.data_ptr_ = other.internal_array_.data();
1499 capacity_ = other.capacity_; other.capacity_ = other.inner_capacity();
1500 size_ = other.size_; other.size_ = 0u;
1501 }
1502 else // otherwise fall back to moving (or at least copying) all elements
1503 {
1504 data_ptr_ = internal_array_.data();
1505 capacity_ = in_capacity;
1506 uninitialized_move_or_copy(other.begin(), other.end(), data());
1507 size_ = other.size();
1508 other.clear();
1509 }
1510 }
1511
1517 static void swap_heap_with_heap(SmallVector &a, SmallVector &b) noexcept
1518 {
1519 std::swap(a.data_ptr_, b.data_ptr_);
1520 std::swap(a.capacity_, b.capacity_);
1521 std::swap(a.size_, b.size_);
1522 }
1523
1530 static void swap_heap_with_internal(SmallVector &a, SmallVector &b)
1531 {
1532 uninitialized_move_or_copy(b.begin(), b.end(),
1533 reinterpret_cast<ValueType*>(a.internal_array_.data()));
1534 destroy_range(b.begin(), b.end());
1535
1536 b.data_ptr_ = a.data_ptr_;
1537 a.data_ptr_ = a.internal_array_.data();
1538
1539 std::swap(a.capacity_, b.capacity_);
1540 std::swap(a.size_, b.size_);
1541 }
1542
1548 static void swap_internal_with_internal(SmallVector &a, SmallVector &b)
1549 {
1550 if (a.size_ <= b.size_)
1551 {
1552 for (SmallVector::SizeType i = 0; i != a.size_; ++i)
1553 std::swap(a.data()[i], b.data()[i]);
1554
1555 uninitialized_move_or_copy(b.begin() + a.size_, b.end(), a.begin() + a.size_);
1556 destroy_range(b.begin() + a.size_, b.end());
1557 }
1558 else
1559 {
1560 for (SizeType i = 0; i != b.size_; ++i)
1561 std::swap(a.data()[i], b.data()[i]);
1562
1563 uninitialized_move_or_copy(a.begin() + b.size_, a.end(), b.begin() + b.size_);
1564 destroy_range(a.begin() + b.size_, a.end());
1565 }
1566
1567 std::swap(a.size_, b.size_);
1568 }
1569
1574 template <typename T>
1575 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value>
1576 uninitialized_move(T* src_begin, T* src_end, T* dest_begin)
1577 {
1578 auto src = src_begin;
1579 auto dest = dest_begin;
1580
1581 try
1582 {
1583 while (src != src_end)
1584 {
1585 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1586 ++src;
1587 ++dest;
1588 }
1589 }
1590 catch (...)
1591 {
1592 for (auto p = dest_begin; p != dest; ++p)
1593 p->~ValueType();
1594
1595 throw;
1596 }
1597 }
1598
1603 template <typename T>
1604 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1605 uninitialized_move(T* src_begin, T* src_end, T* dest_begin) noexcept
1606 {
1607 auto src = src_begin;
1608 auto dest = dest_begin;
1609
1610 while (src != src_end)
1611 {
1612 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1613 ++src;
1614 ++dest;
1615 }
1616 }
1617
1620 template <typename T>
1621 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1622 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin) noexcept
1623 {
1624 uninitialized_move(src_begin, src_end, dest_begin);
1625 }
1626
1629 template <typename T>
1630 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value and
1631 std::is_copy_constructible<T>::value>
1632 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1633 {
1634 std::uninitialized_copy(src_begin, src_end, dest_begin);
1635 }
1636
1639 template <typename T>
1640 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value
1641 and not std::is_copy_constructible<T>::value>
1642 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1643 {
1644 uninitialized_move(src_begin, src_end, dest_begin);
1645 }
1646};
1647
1648
1656template<typename ElementT, size_t in_capacity>
1661
1663
1664} // namespace gul17
1665
1666#endif
1667
1668// 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:271
constexpr Iterator begin() noexcept
Return an iterator to the first element of the vector.
Definition SmallVector.h:528
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:437
Iterator emplace(ConstIterator pos, ArgumentTypes &&... arguments)
Construct an additional element at an arbitrary position in the vector.
Definition SmallVector.h:642
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:909
std::reverse_iterator< ConstIterator > ConstReverseIterator
Iterator to a const element in reversed container.
Definition SmallVector.h:306
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:416
constexpr Reference operator[](SizeType idx)
Return a reference to the element at the specified index.
Definition SmallVector.h:985
constexpr ConstIterator cbegin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:552
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:979
void clear() noexcept
Erase all elements from the container without changing its capacity.
Definition SmallVector.h:570
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:344
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:1050
constexpr Reference at(SizeType idx)
Return a reference to the element at the specified index with bounds-checking.
Definition SmallVector.h:491
Reference reference
Reference to an element.
Definition SmallVector.h:288
constexpr ConstReference operator[](SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:991
constexpr Reference back() noexcept
Return a reference to the last element in the vector.
Definition SmallVector.h:510
ValueType value_type
Type of the elements in the underlying container.
Definition SmallVector.h:276
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:811
ConstReverseIterator crbegin() noexcept
Return a const reverse iterator to the first element of the reversed vector (which is the last elemen...
Definition SmallVector.h:582
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:967
void assign(InputIterator first, InputIterator last)
Fill the vector with copies of elements from the given range.
Definition SmallVector.h:464
ValueType * Iterator
Iterator to an element.
Definition SmallVector.h:294
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:477
Iterator insert(ConstIterator pos, std::initializer_list< ValueType > init)
Insert elements from an initializer list before the indicated position.
Definition SmallVector.h:886
void shrink_to_fit()
Reduce the capacity as far as possible while retaining all stored elements.
Definition SmallVector.h:1156
ElementT ValueType
Type of the elements in the underlying container.
Definition SmallVector.h:274
constexpr ConstIterator cend() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:561
const ValueType & ConstReference
Reference to a const element.
Definition SmallVector.h:290
Iterator iterator
Iterator to an element.
Definition SmallVector.h:296
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:403
~SmallVector()
Destructor: Destroys all stored elements and frees all allocated memory.
Definition SmallVector.h:422
void swap(SmallVector &other)
Exchange the contents of this SmallVector with those of another one.
Definition SmallVector.h:1196
void reserve(SizeType new_capacity)
Increase the capacity of the vector to the specified size.
Definition SmallVector.h:1073
std::ptrdiff_t DifferenceType
Signed integer type for the difference of two iterators.
Definition SmallVector.h:282
constexpr ConstReference front() const noexcept
Return a const reference to the first element in the vector.
Definition SmallVector.h:763
constexpr ConstIterator begin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:537
SmallVector() noexcept=default
Construct an empty SmallVector.
ConstReference const_reference
Reference to a const element.
Definition SmallVector.h:292
Iterator erase(ConstIterator pos)
Erase a single element from the vector, moving elements behind it forward.
Definition SmallVector.h:718
constexpr ValueType * data() noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:602
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:954
SmallVector(InputIterator first, InputIterator last)
Construct a SmallVector that is filled with copies of elements from the given range.
Definition SmallVector.h:367
ReverseIterator rend() noexcept
Return a reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:1060
ValueType & Reference
Reference to an element.
Definition SmallVector.h:286
std::uint32_t SizeType
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:278
SizeType size_type
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:280
constexpr ConstReference back() const noexcept
Return a const reference to the last element in the vector.
Definition SmallVector.h:519
constexpr Reference front() noexcept
Return a reference to the first element in the vector.
Definition SmallVector.h:754
constexpr const ValueType * data() const noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:611
Iterator insert(ConstIterator pos, ValueType &&value)
Insert a single element before the indicated position.
Definition SmallVector.h:797
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:380
constexpr bool empty() const noexcept
Determine if the vector is empty.
Definition SmallVector.h:687
Iterator insert(ConstIterator pos, const ValueType &value)
Insert a single element before the indicated position.
Definition SmallVector.h:783
void resize(SizeType num_elements)
Change the number of elements in the container.
Definition SmallVector.h:1107
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:546
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:936
constexpr ConstIterator end() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:702
constexpr SizeType inner_capacity() const noexcept
Return the number of elements this SmallVector can hold internally without having to allocate storage...
Definition SmallVector.h:772
Reference emplace_back(ArgumentTypes &&... arguments)
Construct an additional element at the end of the buffer.
Definition SmallVector.h:673
void push_back(ValueType &&value)
Move one element to the end of the buffer.
Definition SmallVector.h:1034
Iterator erase(ConstIterator first, ConstIterator last)
Erase a range of elements from the vector, moving elements behind the range forward.
Definition SmallVector.h:736
Iterator insert(ConstIterator pos, InputIterator first, InputIterator last)
Insert a range of values before the indicated position.
Definition SmallVector.h:852
constexpr SizeType max_size() const noexcept
Return the maximum number of elements that this vector can theoretically hold.
Definition SmallVector.h:897
ConstReverseIterator const_reverse_iterator
Iterator to a const element in reversed container.
Definition SmallVector.h:308
ConstIterator const_iterator
Iterator to a const element.
Definition SmallVector.h:300
constexpr ConstReference at(SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:499
void push_back(const ValueType &value)
Copy one element to the end of the buffer.
Definition SmallVector.h:1016
void resize(SizeType num_elements, const ValueType &element)
Change the number of elements in the container.
Definition SmallVector.h:1137
constexpr SizeType size() const noexcept
Return the number of elements that are currently stored.
Definition SmallVector.h:1187
void pop_back()
Remove the last element from the vector.
Definition SmallVector.h:1000
DifferenceType difference_type
Signed integer type for the difference of two iterators.
Definition SmallVector.h:284
ReverseIterator reverse_iterator
Iterator to an element in reversed container.
Definition SmallVector.h:304
std::reverse_iterator< Iterator > ReverseIterator
Iterator to an element in reversed container.
Definition SmallVector.h:302
ConstReverseIterator crend() noexcept
Return a const reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:593
const ValueType * ConstIterator
Iterator to a const element.
Definition SmallVector.h:298
constexpr Iterator end() noexcept
Return an iterator pointing past the last element of the vector.
Definition SmallVector.h:693
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:1657
auto constexpr bit_set(unsigned bit) noexcept -> ReturnT
Set a bit in an integral type.
Definition bit_manip.h:121
std::string cat()
Efficiently concatenate an arbitrary number of strings and numbers.
Definition cat.h:97
Definition of macros used internally by GUL.
Namespace gul17 contains all functions and classes of the General Utility Library.
Definition doxygen.h:26