General Utility Library for C++17 25.4.1
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 <initializer_list>
29#include <iterator>
30#include <limits>
31#include <memory>
32#include <stdexcept>
33#include <type_traits>
34
35#include "gul17/internal.h"
36#include "gul17/cat.h"
37
38namespace gul17 {
39
268template <typename ElementT, size_t in_capacity>
270{
271public:
281 using DifferenceType = std::ptrdiff_t;
289 using ConstReference = const ValueType&;
297 using ConstIterator = const ValueType*;
301 using ReverseIterator = std::reverse_iterator<Iterator>;
305 using ConstReverseIterator = std::reverse_iterator<ConstIterator>;
308
318
326 {
327 static_assert(std::is_default_constructible<ValueType>::value,
328 "SmallVector: Element type is not default-constructible");
329
331 for (SizeType i = 0u; i != num_elements; ++i)
332 ::new(static_cast<void*>(data() + i)) ValueType{};
333 size_ = num_elements;
334 }
335
344 {
345 fill_empty_vector_with_copied_value(num_elements, value);
346 }
347
364 template<class InputIterator,
365 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
367 {
368 fill_empty_vector_with_copied_range(first, last);
369 }
370
380 noexcept(std::is_nothrow_copy_constructible<ValueType>::value)
381 {
382 static_assert(std::is_copy_constructible<ValueType>::value == true,
383 "SmallVector: Element type is not copy-constructible");
384 fill_empty_vector_with_copied_range(other.cbegin(), other.cend());
385 }
386
403 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
404 {
405 move_or_copy_all_elements_from(std::move(other));
406 }
407
415 SmallVector(std::initializer_list<ValueType> init)
416 {
417 fill_empty_vector_with_copied_range(init.begin(), init.end());
418 }
419
422 {
423 clear();
424
425 if (is_storage_allocated())
426 delete[] data_ptr_;
427 }
428
437 {
438 clear();
439 fill_empty_vector_with_copied_value(num_elements, value);
440 }
441
461 template<class InputIterator,
462 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
464 {
465 clear();
466 fill_empty_vector_with_copied_range(first, last);
467 }
468
476 void assign(std::initializer_list<ValueType> init)
477 {
478 const auto num_elements = static_cast<SizeType>(init.size());
479
480 clear();
482 std::uninitialized_copy(init.begin(), init.end(), data());
483 size_ = num_elements;
484 }
485
491 {
492 if (idx >= size_)
493 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
494 return *(data() + idx);
495 }
496
498 constexpr ConstReference at(SizeType idx) const
499 {
500 if (idx >= size_)
501 throw std::out_of_range(cat("Index out of range: ", idx, " >= ", size_));
502 return *(data() + idx);
503 }
504
510 {
511 return *(data_end() - 1);
512 }
513
519 {
520 return *(data_end() - 1);
521 }
522
528 {
529 return data();
530 }
531
537 {
538 return data();
539 }
540
545 constexpr SizeType capacity() const noexcept { return capacity_; }
546
552 {
553 return begin();
554 }
555
561 {
562 return end();
563 }
564
570 {
571 destroy_range(data(), data_end());
572 size_ = 0;
573 }
574
582 {
583 return std::make_reverse_iterator(end());
584 }
585
593 {
594 return std::make_reverse_iterator(begin());
595 }
596
602 {
603 return reinterpret_cast<ValueType*>(data_ptr_);
604 }
605
610 constexpr const ValueType* data() const noexcept
611 {
612 return reinterpret_cast<const ValueType*>(data_ptr_);
613 }
614
640 template <typename... ArgumentTypes>
642 {
643 if (pos == cend())
644 {
645 emplace_back(std::forward<ArgumentTypes>(arguments)...);
646 return data_end() - 1;
647 }
648
649 ValueType v(std::forward<ArgumentTypes>(arguments)...);
650
651 return insert_single_value(pos, std::move(v));
652 }
653
671 template <typename... ArgumentTypes>
673 {
674 if (size_ == capacity_)
675 grow();
676
677 ::new(static_cast<void*>(data_end()))
678 ValueType(std::forward<ArgumentTypes>(arguments)...);
679
680 ++size_;
681
682 return back();
683 }
684
686 constexpr bool empty() const noexcept { return size_ == 0u; }
687
693 {
694 return data_end();
695 }
696
702 {
703 return data_end();
704 }
705
718 {
719 return erase(pos, pos + 1);
720 }
721
736 {
737 auto range_begin = const_cast<Iterator>(first);
738 auto range_end = const_cast<Iterator>(last);
740
741 std::move(range_end, end(), range_begin);
742 destroy_range(end() - num_elements, end());
743
744 size_ -= static_cast<SizeType>(num_elements);
745
746 return range_begin;
747 }
748
754 {
755 return *data();
756 }
757
763 {
764 return *data();
765 }
766
772
783 {
784 return insert_single_value(pos, value);
785 }
786
797 {
798 return insert_single_value(pos, std::move(value));
799 }
800
811 {
812 const auto idx = static_cast<SizeType>(pos - begin());
813 if (num_elements < 1)
814 return begin() + idx;
815
816 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
818
819 // Copy-assign to moved-from elements
820 std::fill_n(insert_pos, num_assignable, value);
821
822 // Copy the remaining values into uninitialized cells
823 copy_value_into_uninitialized_cells(size_, num_elements - num_assignable, value);
824
825 size_ += num_elements;
826
827 return insert_pos;
828 }
829
849 template<class InputIterator,
850 typename = std::enable_if_t<not std::is_integral<InputIterator>::value>>
852 {
853 const auto idx = static_cast<SizeType>(pos - begin());
854 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
855 if (num_elements < 1)
856 return begin() + idx;
857
858 const SizeType num_assignable = make_space_at_idx_for_n_elements(idx, num_elements);
860
861 // Copy-assign to moved-from elements
862 std::copy_n(first, num_assignable, insert_pos);
863
864 // Copy the remaining values into uninitialized cells
865 copy_range_into_uninitialized_cells(size_, first + num_assignable, last);
866
867 size_ += num_elements;
868
869 return insert_pos;
870 }
871
885 Iterator insert(ConstIterator pos, std::initializer_list<ValueType> init)
886 {
887 return insert(pos, init.begin(), init.end());
888 }
889
897 {
898 return std::numeric_limits<SizeType>::max();
899 }
900
909 noexcept(std::is_nothrow_copy_assignable<ValueType>::value)
910 {
911 if (&other != this)
912 {
913 clear();
914 reserve(other.size());
915 std::uninitialized_copy(other.cbegin(), other.cend(), data());
916 size_ = other.size();
917 }
918
919 return *this;
920 }
921
936 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
937 {
938 if (&other != this)
939 {
940 clear();
941 if (is_storage_allocated())
942 delete[] data_ptr_;
943 move_or_copy_all_elements_from(std::move(other));
944 }
945
946 return *this;
947 }
948
953 SmallVector& operator=(std::initializer_list<ValueType> init)
954 {
955 assign(init);
956 return *this;
957 }
958
966 friend bool operator==(const SmallVector& lhs, const SmallVector& rhs)
967 {
968 return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend());
969 }
970
978 friend bool operator!=(const SmallVector& lhs, const SmallVector& rhs)
979 {
980 return not (lhs == rhs);
981 }
982
985 {
986 return *(data() + idx);
987 }
988
991 {
992 return *(data() + idx);
993 }
994
999 void pop_back()
1000 {
1001 --size_;
1002 auto p = data_end();
1003 p->~ValueType();
1004 }
1005
1016 {
1017 if (size_ == capacity_)
1018 grow();
1019
1020 ::new(static_cast<void*>(data_end())) ValueType(value);
1021
1022 ++size_;
1023 }
1024
1034 {
1035 if (size_ == capacity_)
1036 grow();
1037
1038 ::new(static_cast<void*>(data_end())) ValueType(std::move(value));
1039
1040 ++size_;
1041 }
1042
1050 {
1051 return std::make_reverse_iterator(end());
1052 }
1053
1060 {
1061 return std::make_reverse_iterator(begin());
1062 }
1063
1073 {
1074 if (new_capacity <= capacity_)
1075 return;
1076
1077 auto new_data = std::make_unique<AlignedStorage[]>(new_capacity);
1078
1079 const auto d_end = data_end();
1080
1081 uninitialized_move_or_copy(data(), d_end, reinterpret_cast<ValueType*>(new_data.get()));
1082 destroy_range(data(), d_end);
1083
1084 if (is_storage_allocated())
1085 delete[] data_ptr_;
1086
1087 data_ptr_ = new_data.release();
1088 capacity_ = new_capacity;
1089 }
1090
1107 {
1108 static_assert(std::is_default_constructible<ValueType>::value,
1109 "SmallVector: For using resize(), element type must be default-constructible");
1110
1111 if (num_elements < size_)
1112 {
1113 destroy_range(data() + num_elements, data_end());
1114 }
1115 else if (num_elements > size_)
1116 {
1118 fill_uninitialized_cells_with_default_constructed_elements(size_,
1119 num_elements - size_);
1120 }
1121
1122 size_ = num_elements;
1123 }
1124
1137 {
1138 if (num_elements < size_)
1139 {
1140 destroy_range(data() + num_elements, data_end());
1141 }
1142 else if (num_elements > size_)
1143 {
1145 copy_value_into_uninitialized_cells(size_, num_elements - size_, element);
1146 }
1147
1148 size_ = num_elements;
1149 }
1150
1156 {
1157 const SizeType new_capacity = std::max(inner_capacity(), size_);
1158
1159 // No shrinking required?
1160 if (new_capacity == capacity_)
1161 return;
1162
1163 AlignedStorage* new_data;
1164 auto new_memory = std::unique_ptr<AlignedStorage[]>{};
1165
1166 if (new_capacity == inner_capacity()) {
1167 new_data = internal_array_.data();
1168 } else {
1169 new_memory = std::make_unique<AlignedStorage[]>(new_capacity);
1170 new_data = new_memory.get();
1171 }
1172
1173 const auto d_end = data_end();
1174
1175 uninitialized_move_or_copy(data(), d_end, reinterpret_cast<ValueType*>(new_data));
1176 destroy_range(data(), d_end);
1177
1178 if (is_storage_allocated())
1179 delete[] data_ptr_;
1180
1181 data_ptr_ = new_memory ? new_memory.release() : new_data;
1182 capacity_ = new_capacity;
1183 }
1184
1186 constexpr SizeType size() const noexcept { return size_; }
1187
1196 {
1197 if (is_storage_allocated())
1198 {
1199 if (other.is_storage_allocated())
1200 swap_heap_with_heap(*this, other);
1201 else
1202 swap_heap_with_internal(*this, other);
1203 }
1204 else
1205 {
1206 if (other.is_storage_allocated())
1207 swap_heap_with_internal(other, *this);
1208 else
1209 swap_internal_with_internal(*this, other);
1210 }
1211 }
1212
1213private:
1214 using AlignedStorage =
1215 typename std::aligned_storage<sizeof(ValueType), alignof(ValueType)>::type;
1216
1221 std::array<AlignedStorage, in_capacity> internal_array_;
1222
1224 AlignedStorage* data_ptr_{ internal_array_.data() };
1225
1228 SizeType capacity_{ in_capacity };
1230 SizeType size_{ 0u };
1231
1244 template<class InputIterator>
1245 void copy_range_into_uninitialized_cells(SizeType pos, InputIterator first,
1246 InputIterator last)
1247 {
1248 auto data_ptr = data() + pos;
1249
1250 try
1251 {
1252 for (auto it = first; it != last; ++it)
1253 {
1254 ::new(static_cast<void*>(data_ptr)) ValueType{ *it };
1255 ++data_ptr;
1256 }
1257 }
1258 catch (...)
1259 {
1260 for (auto p = data() + pos; p != data_ptr; ++p)
1261 p->~ValueType();
1262
1263 throw;
1264 }
1265 }
1266
1273 void copy_value_into_uninitialized_cells(SizeType pos, SizeType num_elements,
1274 const ValueType& value)
1275 {
1276 const auto start_ptr = data() + pos;
1277 const auto end_ptr = start_ptr + num_elements;
1278 for (auto p = start_ptr; p != end_ptr; ++p)
1279 ::new(static_cast<void*>(p)) ValueType(value);
1280 }
1281
1283 constexpr ValueType* data_end() noexcept
1284 {
1285 return reinterpret_cast<ValueType*>(data_ptr_) + size_;
1286 }
1287
1289 constexpr const ValueType* data_end() const noexcept
1290 {
1291 return reinterpret_cast<const ValueType*>(data_ptr_) + size_;
1292 }
1293
1302 static void destroy_range(Iterator it_start, Iterator it_end) noexcept
1303 {
1304 for (auto it = it_start; it != it_end; ++it)
1305 it->~ValueType();
1306 }
1307
1322 template<typename InputIterator>
1323 void fill_empty_vector_with_copied_range(InputIterator first, InputIterator last)
1324 {
1325 const auto num_elements = static_cast<SizeType>(std::distance(first, last));
1326
1328 copy_range_into_uninitialized_cells(0u, first, last);
1329 size_ = num_elements;
1330 }
1331
1340 void fill_empty_vector_with_copied_value(SizeType num_elements, const ValueType& value)
1341 {
1343 copy_value_into_uninitialized_cells(0u, num_elements, value);
1344 size_ = num_elements;
1345 }
1346
1355 void fill_uninitialized_cells_with_default_constructed_elements(SizeType pos,
1357 {
1358 const auto start_ptr = data() + pos;
1359 const auto end_ptr = start_ptr + num_elements;
1360 auto ptr = start_ptr;
1361
1362 try
1363 {
1364 for (; ptr != end_ptr; ++ptr)
1365 ::new(static_cast<void*>(ptr)) ValueType{};
1366 }
1367 catch (...)
1368 {
1369 destroy_range(start_ptr, ptr);
1370 throw;
1371 }
1372 }
1373
1383 void grow()
1384 {
1385 const auto remaining_space = std::numeric_limits<SizeType>::max() - capacity_;
1386
1387 if (remaining_space == 0u)
1388 throw std::length_error("Max. capacity reached");
1389
1390 SizeType increase = capacity_ / 2u;
1393 else if (increase == 0u)
1394 increase = 1u;
1395
1396 reserve(capacity_ + increase);
1397 }
1398
1400 template <typename T>
1401 Iterator insert_single_value(ConstIterator pos, T&& value)
1402 {
1403 if (pos == end())
1404 {
1405 push_back(std::forward<T>(value));
1406 return begin() + size_ - 1;
1407 }
1408
1409 const auto idx = static_cast<SizeType>(pos - begin());
1410
1411 if (size_ == capacity_)
1412 grow();
1413
1415
1416 auto data_ptr = data();
1417
1418 // Construct new back() element by moving from the old back()
1419 ::new(static_cast<void*>(data_ptr + size_)) ValueType(std::move(*(data_ptr + size_ - 1)));
1420
1421 std::move_backward(insert_pos, data_ptr + size_ - 1, data_ptr + size_);
1422 ++size_;
1423
1424 *insert_pos = std::forward<T>(value);
1425
1426 return insert_pos;
1427 }
1428
1430 bool is_storage_allocated() const noexcept
1431 {
1432 return data_ptr_ != internal_array_.data();
1433 }
1434
1445 SizeType make_space_at_idx_for_n_elements(SizeType idx, SizeType num_elements)
1446 {
1447 const auto new_size = size_ + num_elements;
1448
1449 if (new_size > capacity_)
1451
1452 auto data_ptr = data();
1453
1454 // We have a total number of elements that need to be shifted backwards,
1455 // of which some need to be move-initialized at the end of the vector
1456 // and some simply need to be moved from one element to another.
1457 const SizeType num_shifted = size_ - idx;
1460
1461 // Move-initialize elements in uninitialized space at the back of the container
1462 const auto from_ptr = data_ptr + size_ - num_move_initialized;
1463 const auto to_ptr = from_ptr + num_elements;
1464 for (SizeType i = 0; i != num_move_initialized; ++i)
1465 ::new(static_cast<void*>(to_ptr + i)) ValueType(std::move(*(from_ptr + i)));
1466
1467 // Move elements backwards within old vector size
1468 std::move_backward(data_ptr + idx, data_ptr + idx + num_moved, to_ptr);
1469
1470 return num_move_initialized;
1471 }
1472
1491 void move_or_copy_all_elements_from(SmallVector&& other)
1492 noexcept(std::is_nothrow_move_constructible<ValueType>::value)
1493 {
1494 // Can we simply steal the complete allocated storage?
1495 if (other.is_storage_allocated())
1496 {
1497 data_ptr_ = other.data_ptr_; other.data_ptr_ = other.internal_array_.data();
1498 capacity_ = other.capacity_; other.capacity_ = other.inner_capacity();
1499 size_ = other.size_; other.size_ = 0u;
1500 }
1501 else // otherwise fall back to moving (or at least copying) all elements
1502 {
1503 data_ptr_ = internal_array_.data();
1504 capacity_ = in_capacity;
1505 uninitialized_move_or_copy(other.begin(), other.end(), data());
1506 size_ = other.size();
1507 other.clear();
1508 }
1509 }
1510
1516 static void swap_heap_with_heap(SmallVector &a, SmallVector &b) noexcept
1517 {
1518 std::swap(a.data_ptr_, b.data_ptr_);
1519 std::swap(a.capacity_, b.capacity_);
1520 std::swap(a.size_, b.size_);
1521 }
1522
1529 static void swap_heap_with_internal(SmallVector &a, SmallVector &b)
1530 {
1531 uninitialized_move_or_copy(b.begin(), b.end(),
1532 reinterpret_cast<ValueType*>(a.internal_array_.data()));
1533 destroy_range(b.begin(), b.end());
1534
1535 b.data_ptr_ = a.data_ptr_;
1536 a.data_ptr_ = a.internal_array_.data();
1537
1538 std::swap(a.capacity_, b.capacity_);
1539 std::swap(a.size_, b.size_);
1540 }
1541
1547 static void swap_internal_with_internal(SmallVector &a, SmallVector &b)
1548 {
1549 if (a.size_ <= b.size_)
1550 {
1551 for (SmallVector::SizeType i = 0; i != a.size_; ++i)
1552 std::swap(a.data()[i], b.data()[i]);
1553
1554 uninitialized_move_or_copy(b.begin() + a.size_, b.end(), a.begin() + a.size_);
1555 destroy_range(b.begin() + a.size_, b.end());
1556 }
1557 else
1558 {
1559 for (SizeType i = 0; i != b.size_; ++i)
1560 std::swap(a.data()[i], b.data()[i]);
1561
1562 uninitialized_move_or_copy(a.begin() + b.size_, a.end(), b.begin() + b.size_);
1563 destroy_range(a.begin() + b.size_, a.end());
1564 }
1565
1566 std::swap(a.size_, b.size_);
1567 }
1568
1573 template <typename T>
1574 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value>
1575 uninitialized_move(T* src_begin, T* src_end, T* dest_begin)
1576 {
1577 auto src = src_begin;
1578 auto dest = dest_begin;
1579
1580 try
1581 {
1582 while (src != src_end)
1583 {
1584 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1585 ++src;
1586 ++dest;
1587 }
1588 }
1589 catch (...)
1590 {
1591 for (auto p = dest_begin; p != dest; ++p)
1592 p->~ValueType();
1593
1594 throw;
1595 }
1596 }
1597
1602 template <typename T>
1603 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1604 uninitialized_move(T* src_begin, T* src_end, T* dest_begin) noexcept
1605 {
1606 auto src = src_begin;
1607 auto dest = dest_begin;
1608
1609 while (src != src_end)
1610 {
1611 ::new (static_cast<void*>(dest)) ValueType(std::move(*src));
1612 ++src;
1613 ++dest;
1614 }
1615 }
1616
1619 template <typename T>
1620 static typename std::enable_if_t<std::is_nothrow_move_constructible<T>::value>
1621 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin) noexcept
1622 {
1623 uninitialized_move(src_begin, src_end, dest_begin);
1624 }
1625
1628 template <typename T>
1629 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value and
1630 std::is_copy_constructible<T>::value>
1631 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1632 {
1633 std::uninitialized_copy(src_begin, src_end, dest_begin);
1634 }
1635
1638 template <typename T>
1639 static typename std::enable_if_t<not std::is_nothrow_move_constructible<T>::value
1640 and not std::is_copy_constructible<T>::value>
1641 uninitialized_move_or_copy(T* src_begin, T* src_end, T* dest_begin)
1642 {
1643 uninitialized_move(src_begin, src_end, dest_begin);
1644 }
1645};
1646
1647
1655template<typename ElementT, size_t in_capacity>
1660
1662
1663} // namespace gul17
1664
1665#endif
1666
1667// 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:270
constexpr Iterator begin() noexcept
Return an iterator to the first element of the vector.
Definition SmallVector.h:527
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:436
Iterator emplace(ConstIterator pos, ArgumentTypes &&... arguments)
Construct an additional element at an arbitrary position in the vector.
Definition SmallVector.h:641
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:908
std::reverse_iterator< ConstIterator > ConstReverseIterator
Iterator to a const element in reversed container.
Definition SmallVector.h:305
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:415
constexpr Reference operator[](SizeType idx)
Return a reference to the element at the specified index.
Definition SmallVector.h:984
constexpr ConstIterator cbegin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:551
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:978
uint32_t SizeType
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:277
void clear() noexcept
Erase all elements from the container without changing its capacity.
Definition SmallVector.h:569
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:343
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:1049
constexpr Reference at(SizeType idx)
Return a reference to the element at the specified index with bounds-checking.
Definition SmallVector.h:490
Reference reference
Reference to an element.
Definition SmallVector.h:287
constexpr ConstReference operator[](SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:990
constexpr Reference back() noexcept
Return a reference to the last element in the vector.
Definition SmallVector.h:509
ValueType value_type
Type of the elements in the underlying container.
Definition SmallVector.h:275
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:810
ConstReverseIterator crbegin() noexcept
Return a const reverse iterator to the first element of the reversed vector (which is the last elemen...
Definition SmallVector.h:581
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:966
void assign(InputIterator first, InputIterator last)
Fill the vector with copies of elements from the given range.
Definition SmallVector.h:463
ValueType * Iterator
Iterator to an element.
Definition SmallVector.h:293
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:476
Iterator insert(ConstIterator pos, std::initializer_list< ValueType > init)
Insert elements from an initializer list before the indicated position.
Definition SmallVector.h:885
void shrink_to_fit()
Reduce the capacity as far as possible while retaining all stored elements.
Definition SmallVector.h:1155
ElementT ValueType
Type of the elements in the underlying container.
Definition SmallVector.h:273
constexpr ConstIterator cend() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:560
const ValueType & ConstReference
Reference to a const element.
Definition SmallVector.h:289
Iterator iterator
Iterator to an element.
Definition SmallVector.h:295
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:402
~SmallVector()
Destructor: Destroys all stored elements and frees all allocated memory.
Definition SmallVector.h:421
void swap(SmallVector &other)
Exchange the contents of this SmallVector with those of another one.
Definition SmallVector.h:1195
void reserve(SizeType new_capacity)
Increase the capacity of the vector to the specified size.
Definition SmallVector.h:1072
std::ptrdiff_t DifferenceType
Signed integer type for the difference of two iterators.
Definition SmallVector.h:281
constexpr ConstReference front() const noexcept
Return a const reference to the first element in the vector.
Definition SmallVector.h:762
constexpr ConstIterator begin() const noexcept
Return a const iterator to the first element of the vector.
Definition SmallVector.h:536
SmallVector() noexcept=default
Construct an empty SmallVector.
ConstReference const_reference
Reference to a const element.
Definition SmallVector.h:291
Iterator erase(ConstIterator pos)
Erase a single element from the vector, moving elements behind it forward.
Definition SmallVector.h:717
constexpr ValueType * data() noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:601
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:953
SmallVector(InputIterator first, InputIterator last)
Construct a SmallVector that is filled with copies of elements from the given range.
Definition SmallVector.h:366
ReverseIterator rend() noexcept
Return a reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:1059
ValueType & Reference
Reference to an element.
Definition SmallVector.h:285
SizeType size_type
Unsigned integer type for indexing, number of elements, capacity.
Definition SmallVector.h:279
constexpr ConstReference back() const noexcept
Return a const reference to the last element in the vector.
Definition SmallVector.h:518
constexpr Reference front() noexcept
Return a reference to the first element in the vector.
Definition SmallVector.h:753
constexpr const ValueType * data() const noexcept
Return a pointer to the contiguous data storage of the vector.
Definition SmallVector.h:610
Iterator insert(ConstIterator pos, ValueType &&value)
Insert a single element before the indicated position.
Definition SmallVector.h:796
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:379
constexpr bool empty() const noexcept
Determine if the vector is empty.
Definition SmallVector.h:686
Iterator insert(ConstIterator pos, const ValueType &value)
Insert a single element before the indicated position.
Definition SmallVector.h:782
void resize(SizeType num_elements)
Change the number of elements in the container.
Definition SmallVector.h:1106
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:545
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:935
constexpr ConstIterator end() const noexcept
Return a const iterator pointing past the last element of the vector.
Definition SmallVector.h:701
constexpr SizeType inner_capacity() const noexcept
Return the number of elements this SmallVector can hold internally without having to allocate storage...
Definition SmallVector.h:771
Reference emplace_back(ArgumentTypes &&... arguments)
Construct an additional element at the end of the buffer.
Definition SmallVector.h:672
void push_back(ValueType &&value)
Move one element to the end of the buffer.
Definition SmallVector.h:1033
Iterator erase(ConstIterator first, ConstIterator last)
Erase a range of elements from the vector, moving elements behind the range forward.
Definition SmallVector.h:735
Iterator insert(ConstIterator pos, InputIterator first, InputIterator last)
Insert a range of values before the indicated position.
Definition SmallVector.h:851
constexpr SizeType max_size() const noexcept
Return the maximum number of elements that this vector can theoretically hold.
Definition SmallVector.h:896
ConstReverseIterator const_reverse_iterator
Iterator to a const element in reversed container.
Definition SmallVector.h:307
ConstIterator const_iterator
Iterator to a const element.
Definition SmallVector.h:299
constexpr ConstReference at(SizeType idx) const
Return a const reference to the element at the specified index.
Definition SmallVector.h:498
void push_back(const ValueType &value)
Copy one element to the end of the buffer.
Definition SmallVector.h:1015
void resize(SizeType num_elements, const ValueType &element)
Change the number of elements in the container.
Definition SmallVector.h:1136
constexpr SizeType size() const noexcept
Return the number of elements that are currently stored.
Definition SmallVector.h:1186
void pop_back()
Remove the last element from the vector.
Definition SmallVector.h:999
DifferenceType difference_type
Signed integer type for the difference of two iterators.
Definition SmallVector.h:283
ReverseIterator reverse_iterator
Iterator to an element in reversed container.
Definition SmallVector.h:303
std::reverse_iterator< Iterator > ReverseIterator
Iterator to an element in reversed container.
Definition SmallVector.h:301
ConstReverseIterator crend() noexcept
Return a const reverse iterator pointing past the last element of the reversed vector.
Definition SmallVector.h:592
const ValueType * ConstIterator
Iterator to a const element.
Definition SmallVector.h:297
constexpr Iterator end() noexcept
Return an iterator pointing past the last element of the vector.
Definition SmallVector.h:692
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:1656
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