23#include <initializer_list>
53template <
typename T,
typename...
Args>
56template <
typename T,
typename...
Args>
59template <
typename From,
typename To>
61 std::is_convertible_v<From, To> &&
62 requires(
typename std::add_rvalue_reference_t<From> (&
f)()) {
66template <
typename From,
typename To>
68 std::is_nothrow_convertible_v<From, To> &&
69 requires(
typename std::add_rvalue_reference_t<From> (&
f)()
noexcept) {
70 {
static_cast<To>(
f()) }
noexcept;
77} &&
requires {
::new (
static_cast<void*
>(
nullptr)) T; };
129 requires {
typename X::allocator_type; } &&
130 std::same_as<
typename X::allocator_type,
133 requires (
A m, T*
p,
Args&&... args) {
134 m.construct(
p, std::forward<Args>(args)...);
136 requires (T*
p,
Args&&... args) {
137 { std::construct_at(
p, std::forward<Args>(args)...) } -> std::same_as<T*>;
142 !
requires {
typename X::allocator_type; } &&
143 requires (T*
p,
Args&&... args) {
144 { std::construct_at(
p, std::forward<Args> (args)...) } -> std::same_as<T*>;
149template <
typename T,
typename X,
150 typename A =
typename std::conditional_t<
requires {
151 typename X::allocator_type;
152 },
typename X::allocator_type, std::allocator<T>>>
155template <
typename T,
typename X,
156 typename A =
typename std::conditional_t<
requires {
157 typename X::allocator_type;
158 },
typename X::allocator_type, std::allocator<T>>>
161template <
typename T,
typename X,
162 typename A =
typename std::conditional_t<
requires {
163 typename X::allocator_type;
164 },
typename X::allocator_type, std::allocator<T>>>
170template <
typename T,
typename X,
171 typename A =
typename std::conditional_t<
requires {
172 typename X::allocator_type;
173 },
typename X::allocator_type, std::allocator<T>>>
175 std::same_as<typename X::value_type, T> &&
176 ((
requires {
typename X::allocator_type; }
178 typename X::allocator_type,
180 (
requires(
A m, T*
p) {
m.destroy(
p); } || std::is_destructible_v<T>)) ||
181 (!
requires {
typename X::allocator_type; } && std::is_destructible_v<T>));
188 std::derived_from<T, std::false_type>;
195 requires(T
p, T
q, std::nullptr_t
np) {
197 {
p =
np } -> std::same_as<T&>;
208template <
typename A,
typename T,
typename U = T*>
212 U
xp,
typename std::allocator_traits<A>::pointer
p,
213 typename std::allocator_traits<A>::const_pointer
cp,
214 typename std::allocator_traits<A>::void_pointer
vp,
215 typename std::allocator_traits<A>::const_void_pointer
cvp,
216 typename std::allocator_traits<A>::value_type&
r,
217 typename std::allocator_traits<A>::size_type
n) {
221 requires std::random_access_iterator<
222 typename std::allocator_traits<A>::pointer>;
223 requires std::contiguous_iterator<
224 typename std::allocator_traits<A>::pointer>;
228 typename std::allocator_traits<A>::const_pointer>;
229 requires std::random_access_iterator<
230 typename std::allocator_traits<A>::const_pointer>;
231 requires std::contiguous_iterator<
232 typename std::allocator_traits<A>::const_pointer>;
234 requires std::convertible_to<
235 typename std::allocator_traits<A>::pointer,
236 typename std::allocator_traits<A>::const_pointer>;
241 requires std::convertible_to<
242 typename std::allocator_traits<A>::pointer,
243 typename std::allocator_traits<A>::void_pointer>;
245 requires std::same_as<
246 typename std::allocator_traits<A>::void_pointer,
251 typename std::allocator_traits<A>::const_void_pointer>;
253 requires std::convertible_to<
254 typename std::allocator_traits<A>::pointer,
255 typename std::allocator_traits<A>::const_void_pointer>;
257 requires std::convertible_to<
258 typename std::allocator_traits<A>::const_pointer,
259 typename std::allocator_traits<A>::const_void_pointer>;
261 requires std::convertible_to<
262 typename std::allocator_traits<A>::void_pointer,
263 typename std::allocator_traits<A>::const_void_pointer>;
265 requires std::same_as<
266 typename std::allocator_traits<A>::const_void_pointer,
270 typename A::value_type;
271 requires std::same_as<typename A::value_type, T>;
272 requires std::same_as<
typename A::value_type,
273 typename std::allocator_traits<A>::value_type>;
276 requires std::unsigned_integral<
277 typename std::allocator_traits<A>::size_type>;
280 requires std::signed_integral<
281 typename std::allocator_traits<A>::difference_type>;
285 typename A::template rebind<U>::other;
287 requires std::same_as<
decltype(
b),
288 typename A::template rebind<U>::other>;
289 requires std::same_as<
A,
294 { *
p } -> std::same_as<typename A::value_type&>;
295 { *
cp } -> std::same_as<const typename A::value_type&>;
300 requires std::same_as<
decltype(
p),
typename A::value_type*> ||
requires {
301 {
p.operator->() } -> std::same_as<typename A::value_type*>;
304 requires std::same_as<
decltype(
cp),
const typename A::value_type*> ||
308 } -> std::same_as<const typename A::value_type*>;
311 {
static_cast<decltype(
p)
>(
vp) } -> std::same_as<
decltype(
p)>;
316 } -> std::same_as<
decltype(
p)>;
320 {
a.allocate(
n) } -> std::same_as<
decltype(
p)>;
323 requires !
requires {
a.allocate(
n,
cvp); } ||
requires {
324 {
a.allocate(
n,
cvp) } -> std::same_as<
decltype(
p)>;
328 {
a.deallocate(
p,
n) } -> std::convertible_to<void>;
331 requires !
requires {
a.max_size(); } ||
requires {
332 {
a.max_size() } -> std::same_as<
decltype(
n)>;
336 requires !
requires {
a.construct(
xp); } ||
requires {
337 {
a.construct(
xp) } -> std::convertible_to<void>;
341 requires !
requires {
a.destroy(
xp); } ||
requires {
342 {
a.destroy(
xp) } -> std::convertible_to<void>;
353 requires !
requires {
a.select_on_container_copy_construction(); } ||
356 a.select_on_container_copy_construction()
357 } -> std::same_as<A>;
367 typename std::allocator_traits<A>::propagate_on_container_swap>;
369 {
a ==
b } -> std::same_as<bool>;
370 {
a !=
b } -> std::same_as<bool>;
373 {
a1 ==
a2 } -> std::same_as<bool>;
374 {
a1 !=
a2 } -> std::same_as<bool>;
379 "std::allocator<int> failed to meet Allocator concept requirements.");
410template <
typename T,
typename SmallVector,
typename Alloc>
414template <
typename T,
typename SmallVector,
typename Alloc>
418template <
typename T,
typename SmallVector,
typename Alloc>
422template <
typename T,
typename SmallVector,
typename Alloc>
431template <
typename Alloc,
typename T>
435template <
typename Alloc>
442template <
typename Allocator>
453template <
typename Allocator>
457 template <
typename,
typename Enable =
void>
458 struct is_complete : std::false_type {};
460 template <
typename U>
461 struct is_complete<U, decltype(static_cast<void>(sizeof(U)))>
464 template <
typename U>
465 inline static constexpr bool is_complete_v = is_complete<U>::value;
469 using value_type =
typename std::allocator_traits<allocator_type>::value_type;
472 static_assert(is_complete_v<value_type>,
473 "Calculation of a default number of elements requires that `T` "
476 static constexpr unsigned buffer_max = 256;
478 static constexpr unsigned ideal_total = 64;
480 static constexpr unsigned ideal_buffer =
484 "Empty `small_vector` should not have size 0.");
486 static_assert(ideal_buffer < ideal_total,
487 "Empty `small_vector` is larger than ideal_total.");
489 static constexpr unsigned value = (
sizeof(
value_type) <= ideal_buffer)
494template <
typename Allocator>
498template <
typename Po
inter,
typename DifferenceType>
502 using value_type =
typename std::iterator_traits<Pointer>::value_type;
503 using pointer =
typename std::iterator_traits<Pointer>::pointer;
504 using reference =
typename std::iterator_traits<Pointer>::reference;
506 typename std::iterator_traits<Pointer>::iterator_category;
524 template <
typename U,
typename D>
525 requires std::is_convertible_v<U, Pointer>
528 : m_ptr(other.base()) {}
567 return launder_and_dereference(m_ptr);
573 return launder_and_dereference(m_ptr + n);
576 constexpr const Pointer&
base() const noexcept {
return m_ptr; }
579 static constexpr pointer get_pointer(Pointer ptr)
noexcept
580 requires std::is_pointer_v<Pointer>
585 static constexpr pointer get_pointer(Pointer ptr)
noexcept
586 requires(!std::is_pointer_v<Pointer>)
590 return ptr.operator->();
593 static constexpr reference launder_and_dereference(Pointer ptr)
noexcept
594 requires std::is_pointer_v<Pointer>
596 return *std::launder(ptr);
599 static constexpr reference launder_and_dereference(Pointer ptr)
noexcept
600 requires(!std::is_pointer_v<Pointer>)
613 rhs)
noexcept(
noexcept(
lhs.base() ==
rhs.base()))
615 {
lhs.base() ==
rhs.base() } -> std::convertible_to<bool>;
618 return lhs.base() ==
rhs.base();
621template <
typename Po
inter,
typename DifferenceType>
625 rhs)
noexcept(
noexcept(
lhs.base() ==
rhs.base()))
627 {
lhs.base() ==
rhs.base() } -> std::convertible_to<bool>;
630 return lhs.base() ==
rhs.base();
635 requires std::three_way_comparable_with<PointerLHS, PointerRHS>
639 rhs)
noexcept(
noexcept(
lhs.base() <=>
rhs.base())) {
640 return lhs.base() <=>
rhs.base();
643template <
typename Po
inter,
typename DifferenceType>
644 requires std::three_way_comparable<Pointer>
648 rhs)
noexcept(
noexcept(
lhs.base() <=>
rhs.base())) {
649 return lhs.base() <=>
rhs.base();
657 rhs)
noexcept(
noexcept(
lhs.base() <
rhs.base()) &&
658 noexcept(
rhs.base() <
lhs.base())) {
659 using ordering = std::weak_ordering;
660 return (
lhs.base() <
rhs.base()) ? ordering::less
661 : (
rhs.base() <
lhs.base()) ? ordering::greater
662 : ordering::equivalent;
665template <
typename Po
inter,
typename DifferenceType>
669 rhs)
noexcept(
noexcept(
lhs.base() <
rhs.base()) &&
670 noexcept(
rhs.base() <
lhs.base())) {
671 using ordering = std::weak_ordering;
672 return (
lhs.base() <
rhs.base()) ? ordering::less
673 : (
rhs.base() <
lhs.base()) ? ordering::greater
674 : ordering::equivalent;
677template <
typename Po
interLHS,
typename Po
interRHS,
typename DifferenceType>
684template <
typename Po
inter,
typename DifferenceType>
691template <
typename Po
inter,
typename DifferenceType>
700template <
typename T,
unsigned InlineCapacity>
701class inline_storage {
705 inline_storage() =
default;
706 inline_storage(
const inline_storage&) =
delete;
707 inline_storage(inline_storage&&) noexcept = delete;
708 inline_storage& operator=(const inline_storage&) = delete;
709 inline_storage& operator=(inline_storage&&) noexcept = delete;
710 ~inline_storage() = default;
713 constexpr value_ty* get_inline_ptr() noexcept {
714 return static_cast<value_ty*
>(
static_cast<void*
>(std::addressof(*m_data)));
718 constexpr const value_ty* get_inline_ptr() const noexcept {
719 return static_cast<const value_ty*
>(
720 static_cast<const void*
>(std::addressof(*m_data)));
723 static constexpr size_t element_size() noexcept {
return sizeof(value_ty); }
725 static constexpr size_t alignment() noexcept {
return alignof(value_ty); }
727 static constexpr unsigned num_elements() noexcept {
return InlineCapacity; }
729 static constexpr size_t num_bytes() noexcept {
730 return num_elements() * element_size();
734 alignas(alignment()) std::byte m_data[element_size()][num_elements()];
738class inline_storage<T, 0> {
742 inline_storage() =
default;
743 inline_storage(
const inline_storage&) =
delete;
744 inline_storage(inline_storage&&) noexcept = delete;
745 inline_storage& operator=(const inline_storage&) = delete;
746 inline_storage& operator=(inline_storage&&) noexcept = delete;
747 ~inline_storage() = default;
750 constexpr value_ty* get_inline_ptr() noexcept {
755 constexpr const value_ty* get_inline_ptr() const noexcept {
759 static constexpr size_t element_size() noexcept {
return sizeof(value_ty); }
761 static constexpr size_t alignment() noexcept {
return alignof(value_ty); }
763 static constexpr unsigned num_elements() noexcept {
return 0; }
765 static constexpr size_t num_bytes() noexcept {
return 0; }
768template <
typename Allocator,
769 bool AvailableForEBO =
770 std::is_empty_v<Allocator> && !std::is_final_v<Allocator>>
771class allocator_inliner;
773template <
typename Allocator>
774class allocator_inliner<Allocator, true> :
private Allocator {
775 using alloc_traits = std::allocator_traits<Allocator>;
777 static constexpr bool copy_assign_is_noop =
778 !alloc_traits::propagate_on_container_copy_assignment::value;
780 static constexpr bool move_assign_is_noop =
781 !alloc_traits::propagate_on_container_move_assignment::value;
783 static constexpr bool swap_is_noop =
784 !alloc_traits::propagate_on_container_swap::value;
786 template <
bool IsNoOp = copy_assign_is_noop>
788 constexpr void maybe_assign(
const allocator_inliner&)
noexcept {}
790 template <
bool IsNoOp = copy_assign_is_noop>
792 constexpr void maybe_assign(
const allocator_inliner& other)
noexcept(
793 noexcept(std::declval<Allocator&>().operator=(other))) {
794 Allocator::operator=(other);
797 template <
bool IsNoOp = move_assign_is_noop>
799 constexpr void maybe_assign(allocator_inliner&&) noexcept {}
801 template <
bool IsNoOp = move_assign_is_noop>
803 constexpr void maybe_assign(allocator_inliner&& other)
noexcept(
804 noexcept(std::declval<Allocator&>().operator=(std::move(other)))) {
805 Allocator::operator=(std::move(other));
809 allocator_inliner() =
default;
810 allocator_inliner(
const allocator_inliner&) =
default;
811 allocator_inliner(allocator_inliner&&) noexcept = default;
812 ~allocator_inliner() = default;
814 constexpr explicit allocator_inliner(const Allocator& alloc) noexcept
815 : Allocator(alloc) {}
817 constexpr allocator_inliner&
818 operator=(
const allocator_inliner& other)
noexcept(
819 noexcept(std::declval<allocator_inliner&>().maybe_assign(other))) {
822 "`allocator_inliner` should not participate in self-copy-assignment.");
827 constexpr allocator_inliner& operator=(allocator_inliner&& other)
noexcept(
829 std::declval<allocator_inliner&>().maybe_assign(std::move(other)))) {
832 "`allocator_inliner` should not participate in self-move-assignment.");
833 maybe_assign(std::move(other));
837 constexpr Allocator& allocator_ref() noexcept {
return *
this; }
839 constexpr const Allocator& allocator_ref() const noexcept {
return *
this; }
841 template <
bool IsNoOp = swap_is_noop>
843 constexpr void swap(allocator_inliner&) {}
845 template <
bool IsNoOp = swap_is_noop>
847 constexpr void swap(allocator_inliner& other) {
849 swap(
static_cast<Allocator&
>(*
this),
static_cast<Allocator&
>(other));
853template <
typename Allocator>
854class allocator_inliner<Allocator, false> {
855 using alloc_traits = std::allocator_traits<Allocator>;
857 static constexpr bool copy_assign_is_noop =
858 !alloc_traits::propagate_on_container_copy_assignment::value;
860 static constexpr bool move_assign_is_noop =
861 !alloc_traits::propagate_on_container_move_assignment::value;
863 static constexpr bool swap_is_noop =
864 !alloc_traits::propagate_on_container_swap::value;
866 template <
bool IsNoOp = copy_assign_is_noop>
868 constexpr void maybe_assign(
const allocator_inliner&)
noexcept {}
870 template <
bool IsNoOp = copy_assign_is_noop>
872 constexpr void maybe_assign(
const allocator_inliner& other)
noexcept(
873 noexcept(std::declval<
decltype(other.m_alloc)&>() = other.m_alloc)) {
874 m_alloc = other.m_alloc;
877 template <
bool IsNoOp = move_assign_is_noop>
879 constexpr void maybe_assign(allocator_inliner&&) noexcept {}
881 template <
bool IsNoOp = move_assign_is_noop>
883 constexpr void maybe_assign(allocator_inliner&& other)
noexcept(
noexcept(
884 std::declval<
decltype(other.m_alloc)&>() = std::move(other.m_alloc))) {
885 m_alloc = std::move(other.m_alloc);
889 allocator_inliner() =
default;
890 allocator_inliner(
const allocator_inliner&) =
default;
891 allocator_inliner(allocator_inliner&&) noexcept = default;
892 ~allocator_inliner() = default;
894 constexpr explicit allocator_inliner(const Allocator& alloc) noexcept
897 constexpr allocator_inliner&
898 operator=(
const allocator_inliner& other)
noexcept(
899 noexcept(std::declval<allocator_inliner&>().maybe_assign(other))) {
902 "`allocator_inliner` should not participate in self-copy-assignment.");
907 constexpr allocator_inliner& operator=(allocator_inliner&& other)
noexcept(
909 std::declval<allocator_inliner&>().maybe_assign(std::move(other)))) {
912 "`allocator_inliner` should not participate in self-move-assignment.");
913 maybe_assign(std::move(other));
917 constexpr Allocator& allocator_ref() noexcept {
return m_alloc; }
919 constexpr const Allocator& allocator_ref() const noexcept {
return m_alloc; }
921 template <
bool IsNoOp = swap_is_noop>
923 constexpr void swap(allocator_inliner&) {}
925 template <
bool IsNoOp = swap_is_noop>
927 constexpr void swap(allocator_inliner& other) {
929 swap(m_alloc, other.m_alloc);
936template <
typename Allocator>
937class allocator_interface :
public allocator_inliner<Allocator> {
939 template <
typename U>
940 inline static constexpr bool is_complete_v =
requires {
sizeof(U); };
942 using size_type =
typename std::allocator_traits<Allocator>::size_type;
946 using difference_type =
typename std::conditional_t<
947 (
static_cast<size_t>(
948 (std::numeric_limits<size_type>::max)()) <
949 static_cast<size_t>((std::numeric_limits<
typename std::allocator_traits<
950 Allocator>::difference_type>::max)())),
951 typename std::make_signed_t<size_type>,
952 typename std::allocator_traits<Allocator>::difference_type>;
955 using alloc_base = allocator_inliner<Allocator>;
958 using alloc_ty = Allocator;
959 using alloc_traits = std::allocator_traits<alloc_ty>;
960 using value_ty =
typename alloc_traits::value_type;
961 using ptr =
typename alloc_traits::pointer;
962 using cptr =
typename alloc_traits::const_pointer;
963 using vptr =
typename alloc_traits::void_pointer;
964 using cvptr =
typename alloc_traits::const_void_pointer;
969 using size_ty =
typename std::conditional_t<
970 (
sizeof(size_type) <=
sizeof(uint8_t)), uint_fast8_t,
971 typename std::conditional_t<
972 (
sizeof(size_type) <=
sizeof(uint16_t)), uint_fast16_t,
973 typename std::conditional_t<
974 (
sizeof(size_type) <=
sizeof(uint32_t)), uint_fast32_t,
975 typename std::conditional_t<(
sizeof(size_type) <=
977 uint_fast64_t, size_type>>>>;
979 using diff_ty =
typename std::conditional_t<
980 (
sizeof(difference_type) <=
sizeof(int8_t)), int_fast8_t,
981 typename std::conditional_t<
982 (
sizeof(difference_type) <=
sizeof(int16_t)), int_fast16_t,
983 typename std::conditional_t<
984 (
sizeof(difference_type) <=
sizeof(int32_t)), int_fast32_t,
985 typename std::conditional_t<(
sizeof(difference_type) <=
987 int_fast64_t, difference_type>>>>;
989 using alloc_base::allocator_ref;
992 template <
typename T>
993 struct underlying_if_enum {
997 template <
typename T>
998 requires std::is_enum_v<T>
999 struct underlying_if_enum<T> : std::underlying_type<T> {};
1001 template <
typename T>
1002 using underlying_if_enum_t =
typename underlying_if_enum<T>::type;
1004 template <
typename P>
1005 inline static constexpr bool has_ptr_traits_to_address_v =
1006 requires { std::pointer_traits<P>::to_address(std::declval<P>()); };
1008 template <
typename A,
typename V,
typename... Args>
1009 inline static constexpr bool has_alloc_construct_v =
1010 is_complete_v<V> &&
requires {
1011 std::declval<A&>().construct(std::declval<V*>(),
1012 std::declval<Args>()...);
1015 template <
typename A,
typename V,
typename... Args>
1016 inline static constexpr bool must_use_alloc_construct_v =
1017 !std::is_same_v<A, std::allocator<V>> &&
1018 has_alloc_construct_v<A, V, Args...>;
1020 template <
typename A,
typename V>
1021 inline static constexpr bool has_alloc_destroy_v =
1023 requires { std::declval<A&>().destroy(std::declval<V*>()); };
1025 template <
typename A,
typename V>
1026 inline static constexpr bool must_use_alloc_destroy_v =
1027 !std::is_same_v<A, std::allocator<V>> && has_alloc_destroy_v<A, V>;
1030 allocator_interface() =
default;
1031 allocator_interface(allocator_interface&&) noexcept = default;
1033 constexpr allocator_interface& operator=(const allocator_interface&) =
1036 constexpr allocator_interface& operator=(allocator_interface&&) noexcept =
1039 ~allocator_interface() = default;
1041 constexpr allocator_interface(const allocator_interface& other) noexcept
1042 : alloc_base(alloc_traits::select_on_container_copy_construction(
1043 other.allocator_ref())) {}
1045 constexpr explicit allocator_interface(
const alloc_ty& alloc) noexcept
1046 : alloc_base(alloc) {}
1048 template <
typename T>
1049 constexpr explicit allocator_interface(T&&,
const alloc_ty& alloc) noexcept
1050 : allocator_interface(alloc) {}
1052 template <
typename From,
typename To>
1053 inline static constexpr bool is_memcpyable_integral_v =
1054 is_complete_v<From> &&
1055 (
sizeof(underlying_if_enum_t<From>) ==
1056 sizeof(underlying_if_enum_t<To>)) &&
1057 (std::is_same_v<
bool, underlying_if_enum_t<From>> ==
1058 std::is_same_v<
bool, underlying_if_enum_t<To>>) &&
1059 std::is_integral_v<underlying_if_enum_t<From>> &&
1060 std::is_integral_v<underlying_if_enum_t<To>>;
1062 template <
typename From,
typename To>
1063 inline static constexpr bool is_convertible_pointer_v =
1064 std::is_pointer_v<From> && std::is_pointer_v<To> &&
1065 std::is_convertible_v<From, To>;
1068 template <
typename QualifiedFrom,
typename QualifiedTo = value_ty>
1069 inline static constexpr bool is_memcpyable_v =
1070 is_complete_v<QualifiedFrom> && !std::is_reference_v<QualifiedTo> &&
1071 std::is_trivially_assignable_v<QualifiedTo&, QualifiedFrom> &&
1072 std::is_trivially_copyable_v<std::remove_cv_t<QualifiedTo>> &&
1073 (std::is_same_v<
typename std::remove_cv_t<std::remove_reference_t<
1074 std::remove_cv_t<QualifiedFrom>>>,
1075 std::remove_cv_t<QualifiedTo>> ||
1076 is_memcpyable_integral_v<
1077 std::remove_reference_t<std::remove_cv_t<QualifiedFrom>>,
1078 std::remove_cv_t<QualifiedTo>> ||
1079 is_convertible_pointer_v<
1080 std::remove_reference_t<std::remove_cv_t<QualifiedFrom>>,
1081 std::remove_cv_t<QualifiedTo>>);
1084 template <
typename To,
typename From>
1085 inline static constexpr bool is_uninitialized_memcpyable_v =
1086 !std::is_reference_v<To> && std::is_trivially_constructible_v<To, From> &&
1087 std::is_trivially_copyable_v<std::remove_cv_t<To>> &&
1089 std::remove_cv_t<std::remove_reference_t<std::remove_cv_t<From>>>,
1090 std::remove_cv_t<To>> ||
1091 is_memcpyable_integral_v<std::remove_reference_t<std::remove_cv_t<From>>,
1092 std::remove_cv_t<To>> ||
1093 is_convertible_pointer_v<std::remove_reference_t<std::remove_cv_t<From>>,
1094 std::remove_cv_t<To>>) &&
1095 (!must_use_alloc_construct_v<
1097 std::remove_reference_t<std::remove_cv_t<From>>> &&
1098 !must_use_alloc_destroy_v<alloc_ty, value_ty>);
1100 template <
typename Iterator>
1103 template <
typename... Ts>
1105 : std::true_type {};
1107 template <
typename... Ts>
1108 inline static constexpr bool is_small_vector_iterator_v =
1111 template <
typename InputIt>
1112 inline static constexpr bool is_contiguous_iterator_v =
1113 std::is_same_v<InputIt, ptr> || std::is_same_v<InputIt, cptr> ||
1114 is_small_vector_iterator_v<InputIt> || std::contiguous_iterator<InputIt>;
1116 template <
typename InputIt>
1118 inline static constexpr bool value =
1119 is_memcpyable_v<decltype(*std::declval<InputIt>())> &&
1120 is_contiguous_iterator_v<InputIt>;
1124 template <
typename InputIt>
1128 template <
typename InputIt>
1129 inline static constexpr bool is_memcpyable_iterator_v =
1132 template <
typename InputIt,
typename V = value_ty>
1134 inline static constexpr bool value =
1135 is_uninitialized_memcpyable_v<V, decltype(*std::declval<InputIt>())> &&
1136 is_contiguous_iterator_v<InputIt>;
1140 template <
typename U,
typename V>
1144 template <
typename U,
typename V = value_ty>
1145 inline static constexpr bool is_uninitialized_memcpyable_iterator_v =
1149 static constexpr void throw_range_length_error() {
1150 throw std::length_error(
"The specified range is too long.");
1153 static constexpr value_ty* to_address(value_ty* p)
noexcept {
1154 static_assert(!std::is_function_v<value_ty>,
1155 "value_ty is a function pointer.");
1159 static constexpr const value_ty* to_address(
const value_ty* p)
noexcept {
1160 static_assert(!std::is_function_v<value_ty>,
1161 "value_ty is a function pointer.");
1165 template <
typename Po
inter>
1166 requires has_ptr_traits_to_address_v<Pointer>
1167 static constexpr auto to_address(
const Pointer& p)
noexcept
1168 ->
decltype(std::pointer_traits<Pointer>::to_address(p)) {
1169 return std::pointer_traits<Pointer>::to_address(p);
1172 template <
typename Po
inter>
1173 requires(!has_ptr_traits_to_address_v<Pointer>)
1174 static constexpr auto to_address(
const Pointer& p)
noexcept
1175 ->
decltype(to_address(p.operator->())) {
1176 return to_address(p.operator->());
1179 template <
typename Integer>
1181 static consteval size_t numeric_max() noexcept {
1182 static_assert(0 <= (std::numeric_limits<Integer>::max)(),
1183 "Integer is nonpositive.");
1184 return static_cast<size_t>((std::numeric_limits<Integer>::max)());
1188 static constexpr size_ty internal_range_length(cptr first,
1189 cptr last)
noexcept {
1191 return static_cast<size_ty
>(last - first);
1194 template <
typename RandomIt>
1196 static constexpr size_ty external_range_length_impl(
1197 RandomIt first, RandomIt last, std::random_access_iterator_tag) {
1198 assert(0 <= (last - first) &&
"Invalid range.");
1199 const auto len =
static_cast<size_t>(last - first);
1201 if (numeric_max<size_ty>() < len)
1202 throw_range_length_error();
1204 return static_cast<size_ty
>(len);
1207 template <
typename ForwardIt>
1209 static constexpr size_ty external_range_length_impl(
1210 ForwardIt first, ForwardIt last, std::forward_iterator_tag) {
1211 if (std::is_constant_evaluated()) {
1214 typename std::iterator_traits<ForwardIt>::difference_type len = 0;
1215 for (; !(first == last); ++first) {
1218 assert(
static_cast<size_t>(len) <= numeric_max<size_ty>());
1219 return static_cast<size_ty
>(len);
1222 const auto len =
static_cast<size_t>(std::distance(first, last));
1224 if (numeric_max<size_ty>() < len)
1225 throw_range_length_error();
1227 return static_cast<size_ty
>(len);
1230 template <
typename ForwardIt,
1232 typename std::iterator_traits<ForwardIt>::difference_type>
1233 requires(numeric_max<size_ty>() < numeric_max<ItDiffT>())
1235 static constexpr size_ty external_range_length(ForwardIt first,
1237 using iterator_cat =
1238 typename std::iterator_traits<ForwardIt>::iterator_category;
1239 return external_range_length_impl(first, last, iterator_cat{});
1242 template <
typename ForwardIt,
1244 typename std::iterator_traits<ForwardIt>::difference_type>
1245 requires(!(numeric_max<size_ty>() < numeric_max<ItDiffT>()))
1247 static constexpr size_ty external_range_length(ForwardIt first,
1248 ForwardIt last)
noexcept {
1249 if (std::is_constant_evaluated()) {
1253 for (; !(first == last); ++first) {
1259 return static_cast<size_ty
>(std::distance(first, last));
1262 template <
typename Iterator,
1263 typename IteratorDiffT =
1264 typename std::iterator_traits<Iterator>::difference_type,
1265 typename Integer = IteratorDiffT>
1267 static constexpr Iterator unchecked_next(Iterator pos,
1268 Integer n = 1) noexcept {
1269 unchecked_advance(pos,
static_cast<IteratorDiffT
>(n));
1273 template <
typename Iterator,
1274 typename IteratorDiffT =
1275 typename std::iterator_traits<Iterator>::difference_type,
1276 typename Integer = IteratorDiffT>
1278 static constexpr Iterator unchecked_prev(Iterator pos,
1279 Integer n = 1) noexcept {
1280 unchecked_advance(pos, -
static_cast<IteratorDiffT
>(n));
1284 template <
typename Iterator,
1285 typename IteratorDiffT =
1286 typename std::iterator_traits<Iterator>::difference_type,
1287 typename Integer = IteratorDiffT>
1288 static constexpr void unchecked_advance(Iterator& pos, Integer n)
noexcept {
1289 std::advance(pos,
static_cast<IteratorDiffT
>(n));
1293 constexpr size_ty get_max_size() const noexcept {
1296 static_cast<size_ty
>(alloc_traits::max_size(allocator_ref())),
1297 static_cast<size_ty
>(numeric_max<difference_type>()));
1301 constexpr ptr allocate(size_ty n) {
1302 return alloc_traits::allocate(allocator_ref(),
static_cast<size_type
>(n));
1306 constexpr ptr allocate_with_hint(size_ty n, cptr hint) {
1307 return alloc_traits::allocate(allocator_ref(),
static_cast<size_type
>(n),
1311 constexpr void deallocate(ptr p, size_ty n) {
1312 alloc_traits::deallocate(allocator_ref(), to_address(p),
1313 static_cast<size_type
>(n));
1316 template <
typename U>
1317 requires is_uninitialized_memcpyable_v<value_ty, U>
1318 constexpr void construct(ptr p, U&& val)
noexcept {
1319 if (std::is_constant_evaluated()) {
1320 alloc_traits::construct(allocator_ref(), to_address(p),
1321 std::forward<U>(val));
1324 std::memcpy(to_address(p), &val,
sizeof(value_ty));
1329 template <
typename A = alloc_ty,
typename V = value_ty,
typename... Args>
1330 requires(
sizeof...(Args) != 1 ||
1331 !is_uninitialized_memcpyable_v<V, Args...>) &&
1332 has_alloc_construct_v<A, V, Args...>
1333 constexpr void construct(ptr p, Args&&... args)
noexcept(
1334 noexcept(alloc_traits::construct(std::declval<alloc_ty&>(),
1335 std::declval<value_ty*>(),
1336 std::forward<Args>(args)...))) {
1337 alloc_traits::construct(allocator_ref(), to_address(p),
1338 std::forward<Args>(args)...);
1341 template <
typename A = alloc_ty,
typename V = value_ty,
typename... Args>
1342 requires(
sizeof...(Args) != 1 ||
1343 !is_uninitialized_memcpyable_v<V, Args...>) &&
1344 (!has_alloc_construct_v<A, V, Args...>) &&
requires {
1345 ::new (std::declval<void*>()) V(std::declval<Args>()...);
1347 constexpr
void construct(ptr p, Args&&... args) noexcept(noexcept(
1348 ::new(std::declval<
void*>()) value_ty(std::declval<Args>()...))) {
1349 construct_at(to_address(p), std::forward<Args>(args)...);
1352 template <
typename A = alloc_ty,
typename V = value_ty>
1353 requires std::is_trivially_destructible_v<V> &&
1354 (!must_use_alloc_destroy_v<A, V>)
1355 constexpr void destroy(ptr)
const noexcept {}
1357 template <
typename A = alloc_ty,
typename V = value_ty>
1358 requires(!std::is_trivially_destructible_v<V> ||
1359 must_use_alloc_destroy_v<A, V>) &&
1360 has_alloc_destroy_v<A, V>
1361 constexpr void destroy(ptr p)
noexcept {
1362 alloc_traits::destroy(allocator_ref(), to_address(p));
1366 template <
typename A = alloc_ty,
typename V = value_ty>
1367 requires(!std::is_trivially_destructible_v<V> ||
1368 must_use_alloc_destroy_v<A, V>) &&
1369 (!has_alloc_destroy_v<A, V>)
1370 constexpr void destroy(ptr p)
noexcept {
1371 destroy_at(to_address(p));
1374 template <
typename A = alloc_ty,
typename V = value_ty>
1375 requires std::is_trivially_destructible_v<V> &&
1376 (!must_use_alloc_destroy_v<A, V>)
1377 constexpr void destroy_range(ptr, ptr)
const noexcept {}
1379 template <
typename A = alloc_ty,
typename V = value_ty>
1380 requires(!std::is_trivially_destructible_v<V> ||
1381 must_use_alloc_destroy_v<A, V>)
1382 constexpr void destroy_range(ptr first, ptr last)
noexcept {
1383 for (; !(first == last); ++first) {
1390 template <
typename ForwardIt>
1391 requires is_uninitialized_memcpyable_iterator_v<ForwardIt>
1392 constexpr ptr uninitialized_copy(ForwardIt first, ForwardIt last,
1393 ptr dest)
noexcept {
1394 static_assert(std::is_constructible_v<value_ty,
decltype(*first)>,
1395 "`value_type` must be copy constructible.");
1397 if (std::is_constant_evaluated()) {
1398 return default_uninitialized_copy(first, last, dest);
1401 const size_ty num_copy = external_range_length(first, last);
1402 if (num_copy != 0) {
1403 std::memcpy(to_address(dest), to_address(first),
1404 num_copy *
sizeof(value_ty));
1406 return unchecked_next(dest, num_copy);
1409 template <
typename ForwardIt>
1410 requires is_uninitialized_memcpyable_iterator_v<ForwardIt>
1411 constexpr ptr uninitialized_copy(std::move_iterator<ForwardIt> first,
1412 std::move_iterator<ForwardIt> last,
1413 ptr dest)
noexcept {
1414 return uninitialized_copy(first.base(), last.base(), dest);
1417 template <
typename InputIt>
1418 requires(!is_uninitialized_memcpyable_iterator_v<InputIt>)
1419 constexpr ptr uninitialized_copy(InputIt first, InputIt last, ptr d_first) {
1420 return default_uninitialized_copy(first, last, d_first);
1423 template <
typename InputIt>
1424 constexpr ptr default_uninitialized_copy(InputIt first, InputIt last,
1426 ptr d_last = d_first;
1428 for (; !(first == last); ++first,
static_cast<void>(++d_last)) {
1429 construct(d_last, *first);
1433 destroy_range(d_first, d_last);
1438 template <
typename A = alloc_ty,
typename V = value_ty>
1439 requires(std::is_trivially_constructible_v<V> &&
1440 !must_use_alloc_construct_v<A, V>)
1441 constexpr ptr uninitialized_value_construct(ptr first, ptr last) {
1442 if (std::is_constant_evaluated()) {
1443 return default_uninitialized_value_construct(first, last);
1445 std::fill(first, last, value_ty());
1449 template <
typename A = alloc_ty,
typename V = value_ty>
1450 requires(!std::is_trivially_constructible_v<V> ||
1451 must_use_alloc_construct_v<A, V>)
1452 constexpr ptr uninitialized_value_construct(ptr first, ptr last) {
1453 return default_uninitialized_value_construct(first, last);
1456 constexpr ptr default_uninitialized_value_construct(ptr first, ptr last) {
1459 for (; !(curr == last); ++curr) {
1464 destroy_range(first, curr);
1469 constexpr ptr uninitialized_fill(ptr first, ptr last) {
1470 return uninitialized_value_construct(first, last);
1473 constexpr ptr uninitialized_fill(ptr first, ptr last,
const value_ty& val) {
1476 for (; !(curr == last); ++curr) {
1477 construct(curr, val);
1481 destroy_range(first, curr);
1490 template <
typename V = value_ty>
1491 requires std::is_array_v<V>
1492 static constexpr void destroy_at(value_ty* p)
noexcept {
1493 for (
auto& e : *p) {
1494 destroy_at(std::addressof(e));
1498 template <
typename V = value_ty>
1499 requires(!std::is_array_v<V>)
1500 static constexpr void destroy_at(value_ty* p)
noexcept {
1504 template <
typename V = value_ty,
typename... Args>
1505 static constexpr auto construct_at(value_ty* p, Args&&... args)
noexcept(
1506 noexcept(::new(std::declval<void*>()) V(std::declval<Args>()...)))
1507 -> decltype(::new(std::declval<
void*>()) V(std::declval<Args>()...)) {
1508 if (std::is_constant_evaluated()) {
1509 return std::construct_at(p, std::forward<Args>(args)...);
1511 void* vp =
const_cast<void*
>(
static_cast<const volatile void*
>(p));
1512 return ::new (vp) value_ty(std::forward<Args>(args)...);
1516template <
typename Po
inter,
typename SizeT>
1517class small_vector_data_base {
1519 using ptr = Pointer;
1520 using size_ty = SizeT;
1522 small_vector_data_base() =
default;
1523 small_vector_data_base(
const small_vector_data_base&) =
default;
1524 small_vector_data_base(small_vector_data_base&&) noexcept = default;
1525 small_vector_data_base& operator=(const small_vector_data_base&) = default;
1526 small_vector_data_base& operator=(small_vector_data_base&&) noexcept =
1528 ~small_vector_data_base() = default;
1530 constexpr ptr data_ptr() const noexcept {
return m_data_ptr; }
1531 constexpr size_ty capacity() const noexcept {
return m_capacity; }
1532 constexpr size_ty
size() const noexcept {
return m_size; }
1534 constexpr void set_data_ptr(ptr data_ptr)
noexcept { m_data_ptr = data_ptr; }
1535 constexpr void set_capacity(size_ty capacity)
noexcept {
1536 m_capacity = capacity;
1538 constexpr void set_size(size_ty size)
noexcept { m_size =
size; }
1540 constexpr void set(ptr data_ptr, size_ty capacity, size_ty size) {
1541 m_data_ptr = data_ptr;
1542 m_capacity = capacity;
1546 constexpr void swap_data_ptr(small_vector_data_base& other)
noexcept {
1548 swap(m_data_ptr, other.m_data_ptr);
1551 constexpr void swap_capacity(small_vector_data_base& other)
noexcept {
1553 swap(m_capacity, other.m_capacity);
1556 constexpr void swap_size(small_vector_data_base& other)
noexcept {
1558 swap(m_size, other.m_size);
1561 constexpr void swap(small_vector_data_base& other)
noexcept {
1563 swap(m_data_ptr, other.m_data_ptr);
1564 swap(m_capacity, other.m_capacity);
1565 swap(m_size, other.m_size);
1574template <
typename Po
inter,
typename SizeT,
typename T,
unsigned InlineCapacity>
1575class small_vector_data :
public small_vector_data_base<Pointer, SizeT> {
1579 small_vector_data() =
default;
1580 small_vector_data(
const small_vector_data&) =
delete;
1581 small_vector_data(small_vector_data&&) noexcept = delete;
1582 small_vector_data& operator=(const small_vector_data&) = delete;
1583 small_vector_data& operator=(small_vector_data&&) noexcept = delete;
1584 ~small_vector_data() = default;
1586 constexpr value_ty* storage() noexcept {
return m_storage.get_inline_ptr(); }
1588 constexpr const value_ty* storage() const noexcept {
1589 return m_storage.get_inline_ptr();
1593 inline_storage<value_ty, InlineCapacity> m_storage;
1596template <
typename Po
inter,
typename SizeT,
typename T>
1597class small_vector_data<Pointer, SizeT, T, 0>
1598 :
public small_vector_data_base<Pointer, SizeT>,
1599 private inline_storage<T, 0> {
1600 using base = inline_storage<T, 0>;
1605 small_vector_data() =
default;
1606 small_vector_data(
const small_vector_data&) =
delete;
1607 small_vector_data(small_vector_data&&) noexcept = delete;
1608 small_vector_data& operator=(const small_vector_data&) = delete;
1609 small_vector_data& operator=(small_vector_data&&) noexcept = delete;
1610 ~small_vector_data() = default;
1612 constexpr value_ty* storage() noexcept {
return base::get_inline_ptr(); }
1614 constexpr const value_ty* storage() const noexcept {
1615 return base::get_inline_ptr();
1619template <
typename Allocator,
unsigned InlineCapacity>
1620class small_vector_base :
public allocator_interface<Allocator> {
1622 using size_type =
typename allocator_interface<Allocator>::size_type;
1623 using difference_type =
1624 typename allocator_interface<Allocator>::difference_type;
1626 template <
typename SameAllocator,
unsigned DifferentInlineCapacity>
1627 friend class small_vector_base;
1630 using alloc_interface = allocator_interface<Allocator>;
1631 using alloc_traits =
typename alloc_interface::alloc_traits;
1632 using alloc_ty = Allocator;
1634 using value_ty =
typename alloc_interface::value_ty;
1635 using ptr =
typename alloc_interface::ptr;
1636 using cptr =
typename alloc_interface::cptr;
1637 using size_ty =
typename alloc_interface::size_ty;
1638 using diff_ty =
typename alloc_interface::diff_ty;
1641 alloc_interface::template is_complete_v<value_ty> || InlineCapacity == 0,
1642 "`value_type` must be complete for instantiation of a non-zero number "
1643 "of inline elements.");
1645 template <
typename T>
1646 inline static constexpr bool is_complete_v =
1647 alloc_interface::template is_complete_v<T>;
1649 using alloc_interface::allocator_ref;
1650 using alloc_interface::construct;
1651 using alloc_interface::deallocate;
1652 using alloc_interface::destroy;
1653 using alloc_interface::destroy_range;
1654 using alloc_interface::external_range_length;
1655 using alloc_interface::get_max_size;
1656 using alloc_interface::internal_range_length;
1657 using alloc_interface::to_address;
1658 using alloc_interface::unchecked_advance;
1659 using alloc_interface::unchecked_next;
1660 using alloc_interface::unchecked_prev;
1661 using alloc_interface::uninitialized_copy;
1662 using alloc_interface::uninitialized_fill;
1663 using alloc_interface::uninitialized_value_construct;
1665 template <
typename Integer>
1667 static consteval size_t numeric_max() noexcept {
1668 return alloc_interface::template numeric_max<Integer>();
1672 static consteval size_ty get_inline_capacity() noexcept {
1673 return static_cast<size_ty
>(InlineCapacity);
1676 template <
typename... Args>
1677 inline static constexpr bool is_emplace_constructible_v =
1678 is_complete_v<Args...> &&
requires {
1679 std::declval<alloc_interface&>().construct(std::declval<value_ty*>(),
1680 std::declval<Args>()...);
1683 template <
typename... Args>
1684 inline static constexpr bool is_nothrow_emplace_constructible_v =
1685 is_complete_v<Args...> &&
requires {
1686 noexcept(std::declval<alloc_interface&>().construct(
1687 std::declval<value_ty*>(), std::declval<Args>()...));
1690 template <
typename V = value_ty>
1691 inline static constexpr bool is_explicitly_move_insertable_v =
1692 is_emplace_constructible_v<V&&>;
1694 template <
typename V = value_ty>
1695 inline static constexpr bool is_explicitly_nothrow_move_insertable_v =
1696 is_nothrow_emplace_constructible_v<V&&>;
1698 template <
typename V = value_ty>
1699 inline static constexpr bool is_explicitly_copy_insertable_v =
1700 is_emplace_constructible_v<V&> && is_emplace_constructible_v<const V&>;
1702 template <
typename V = value_ty>
1703 inline static constexpr bool is_explicitly_nothrow_copy_insertable_v =
1704 is_nothrow_emplace_constructible_v<V&> &&
1705 is_nothrow_emplace_constructible_v<const V&>;
1707 template <
typename V>
1708 inline static constexpr bool relocate_with_move_v =
1709 std::is_nothrow_move_constructible_v<V> ||
1710 !is_explicitly_copy_insertable_v<V>;
1712 template <
typename A>
1713 inline static constexpr bool allocations_are_movable_v =
1714 std::is_same_v<std::allocator<value_ty>, A> ||
1715 std::allocator_traits<A>::propagate_on_container_move_assignment::value ||
1716 std::allocator_traits<A>::is_always_equal::value;
1718 template <
typename A>
1719 inline static constexpr bool allocations_are_swappable_v =
1720 std::is_same_v<std::allocator<value_ty>, A> ||
1721 std::allocator_traits<A>::propagate_on_container_swap::value ||
1722 std::allocator_traits<A>::is_always_equal::value;
1724 template <
typename... Args>
1725 inline static constexpr bool is_memcpyable_v =
1726 alloc_interface::template is_memcpyable_v<Args...>;
1728 template <
typename... Args>
1729 inline static constexpr bool is_memcpyable_iterator_v =
1730 alloc_interface::template is_memcpyable_iterator_v<Args...>;
1733 static constexpr void throw_overflow_error() {
1734 throw std::overflow_error(
"The requested conversion would overflow.");
1738 static constexpr void throw_index_error() {
1739 throw std::out_of_range(
"The requested index was out of range.");
1743 static constexpr void throw_increment_error() {
1744 throw std::domain_error(
1745 "The requested increment was outside of the allowed range.");
1749 static constexpr void throw_allocation_size_error() {
1750 throw std::length_error(
1751 "The required allocation exceeds the maximum size.");
1755 constexpr ptr ptr_cast(
1756 const small_vector_iterator<cptr, diff_ty>& it)
noexcept {
1757 return unchecked_next(begin_ptr(), it.base() - begin_ptr());
1761 class stack_temporary {
1763 stack_temporary() =
delete;
1764 stack_temporary(
const stack_temporary&) =
delete;
1765 stack_temporary(stack_temporary&&) noexcept = delete;
1766 stack_temporary& operator=(const stack_temporary&) = delete;
1767 stack_temporary& operator=(stack_temporary&&) noexcept = delete;
1769 template <typename... Args>
1770 constexpr explicit stack_temporary(alloc_interface& alloc_iface,
1772 : m_interface(alloc_iface) {
1773 m_interface.construct(get_pointer(), std::forward<Args>(args)...);
1776 constexpr ~stack_temporary() { m_interface.destroy(get_pointer()); }
1779 constexpr const value_ty& get() const noexcept {
1780 return *get_pointer();
1784 constexpr value_ty&& release() noexcept {
1785 return std::move(*get_pointer());
1790 constexpr cptr get_pointer() const noexcept {
1791 return static_cast<cptr
>(
1792 static_cast<const void*
>(std::addressof(m_data)));
1796 constexpr ptr get_pointer() noexcept {
1797 return static_cast<ptr
>(
static_cast<void*
>(std::addressof(m_data)));
1800 alloc_interface& m_interface;
1801 alignas(value_ty) std::byte m_data[
sizeof(value_ty)];
1804 class heap_temporary {
1806 heap_temporary() =
delete;
1807 heap_temporary(
const heap_temporary&) =
delete;
1808 heap_temporary(heap_temporary&&) noexcept = delete;
1809 heap_temporary& operator=(const heap_temporary&) = delete;
1810 heap_temporary& operator=(heap_temporary&&) noexcept = delete;
1812 template <typename... Args>
1813 constexpr explicit heap_temporary(alloc_interface& alloc_iface,
1815 : m_interface(alloc_iface),
1816 m_data_ptr(alloc_iface.allocate(sizeof(value_ty))) {
1818 m_interface.construct(m_data_ptr, std::forward<Args>(args)...);
1820 m_interface.deallocate(m_data_ptr,
sizeof(value_ty));
1825 constexpr ~heap_temporary() {
1826 m_interface.destroy(m_data_ptr);
1827 m_interface.deallocate(m_data_ptr,
sizeof(value_ty));
1831 constexpr const value_ty& get() const noexcept {
1836 constexpr value_ty&& release() noexcept {
1837 return std::move(*m_data_ptr);
1841 alloc_interface& m_interface;
1845 constexpr void wipe() {
1846 destroy_range(begin_ptr(), end_ptr());
1847 if (has_allocation()) {
1848 deallocate(data_ptr(), get_capacity());
1852 constexpr void set_data_ptr(ptr data_ptr)
noexcept {
1853 m_data.set_data_ptr(data_ptr);
1856 constexpr void set_capacity(size_ty capacity)
noexcept {
1857 m_data.set_capacity(
static_cast<size_type
>(capacity));
1860 constexpr void set_size(size_ty size)
noexcept {
1861 m_data.set_size(
static_cast<size_type
>(size));
1864 constexpr void set_data(ptr data_ptr, size_ty capacity,
1865 size_ty size)
noexcept {
1866 m_data.set(data_ptr,
static_cast<size_type
>(capacity),
1867 static_cast<size_type
>(size));
1870 constexpr void swap_data_ptr(small_vector_base& other)
noexcept {
1871 m_data.swap_data_ptr(other.m_data);
1874 constexpr void swap_capacity(small_vector_base& other)
noexcept {
1875 m_data.swap_capacity(other.m_data);
1878 constexpr void swap_size(small_vector_base& other)
noexcept {
1879 m_data.swap_size(other.m_data);
1882 constexpr void swap_allocation(small_vector_base& other)
noexcept {
1883 m_data.swap(other.m_data);
1886 constexpr void reset_data(ptr data_ptr, size_ty capacity, size_ty size) {
1888 m_data.set(data_ptr,
static_cast<size_type
>(capacity),
1889 static_cast<size_type
>(size));
1892 constexpr void increase_size(size_ty n)
noexcept {
1893 m_data.set_size(get_size() + n);
1896 constexpr void decrease_size(size_ty n)
noexcept {
1897 m_data.set_size(get_size() - n);
1900 constexpr ptr unchecked_allocate(size_ty n) {
1901 assert(InlineCapacity < n &&
1902 "Allocated capacity should be greater than InlineCapacity.");
1903 return alloc_interface::allocate(n);
1906 constexpr ptr unchecked_allocate(size_ty n, cptr hint) {
1907 assert(InlineCapacity < n &&
1908 "Allocated capacity should be greater than InlineCapacity.");
1909 return alloc_interface::allocate_with_hint(n, hint);
1912 constexpr ptr checked_allocate(size_ty n) {
1913 if (get_max_size() < n) {
1914 throw_allocation_size_error();
1916 return unchecked_allocate(n);
1921 constexpr size_ty unchecked_calculate_new_capacity(
1922 const size_ty minimum_required_capacity)
const noexcept {
1923 const size_ty current_capacity = get_capacity();
1925 assert(current_capacity < minimum_required_capacity);
1927 if (get_max_size() - current_capacity <= current_capacity) {
1928 return get_max_size();
1935 const size_ty new_capacity = 2 * current_capacity;
1936 if (new_capacity < minimum_required_capacity) {
1937 return minimum_required_capacity;
1939 return new_capacity;
1943 constexpr size_ty checked_calculate_new_capacity(
1944 const size_ty minimum_required_capacity)
const {
1945 if (get_max_size() < minimum_required_capacity) {
1946 throw_allocation_size_error();
1948 return unchecked_calculate_new_capacity(minimum_required_capacity);
1951 template <
unsigned I>
1952 constexpr small_vector_base& copy_assign_default(
1953 const small_vector_base<Allocator, I>& other) {
1954 if (get_capacity() < other.get_size()) {
1956 size_ty new_capacity = unchecked_calculate_new_capacity(other.get_size());
1958 unchecked_allocate(new_capacity, other.allocation_end_ptr());
1961 uninitialized_copy(other.begin_ptr(), other.end_ptr(), new_data_ptr);
1963 deallocate(new_data_ptr, new_capacity);
1967 reset_data(new_data_ptr, new_capacity, other.get_size());
1969 if (get_size() < other.get_size()) {
1971 std::copy_n(other.begin_ptr(), get_size(), begin_ptr());
1972 uninitialized_copy(unchecked_next(other.begin_ptr(), get_size()),
1973 other.end_ptr(), end_ptr());
1976 copy_range(other.begin_ptr(), other.end_ptr(), begin_ptr()),
1981 set_size(other.get_size());
1984 alloc_interface::operator=(other);
1988 template <
unsigned I,
typename AT = alloc_traits>
1989 requires(AT::propagate_on_container_copy_assignment::value &&
1990 !AT::is_always_equal::value)
1991 constexpr small_vector_base& copy_assign(
1992 const small_vector_base<Allocator, I>& other) {
1993 if (other.allocator_ref() == allocator_ref()) {
1994 return copy_assign_default(other);
1997 if (InlineCapacity < other.get_size()) {
1998 alloc_interface new_alloc(other);
2000 const size_ty new_capacity = other.get_size();
2001 const ptr new_data_ptr = new_alloc.allocate_with_hint(
2002 new_capacity, other.allocation_end_ptr());
2005 uninitialized_copy(other.begin_ptr(), other.end_ptr(), new_data_ptr);
2007 new_alloc.deallocate(new_data_ptr, new_capacity);
2011 reset_data(new_data_ptr, new_capacity, other.get_size());
2012 alloc_interface::operator=(new_alloc);
2014 if (has_allocation()) {
2016 if (std::is_constant_evaluated()) {
2017 alloc_interface new_alloc(other);
2018 new_data_ptr = new_alloc.allocate(InlineCapacity);
2020 new_data_ptr = storage_ptr();
2023 uninitialized_copy(other.begin_ptr(), other.end_ptr(), new_data_ptr);
2024 destroy_range(begin_ptr(), end_ptr());
2025 deallocate(data_ptr(), get_capacity());
2026 set_data_ptr(new_data_ptr);
2027 set_capacity(InlineCapacity);
2028 }
else if (get_size() < other.get_size()) {
2029 std::copy_n(other.begin_ptr(), get_size(), begin_ptr());
2030 uninitialized_copy(unchecked_next(other.begin_ptr(), get_size()),
2031 other.end_ptr(), end_ptr());
2034 copy_range(other.begin_ptr(), other.end_ptr(), begin_ptr()),
2037 set_size(other.get_size());
2038 alloc_interface::operator=(other);
2044 template <
unsigned I,
typename AT = alloc_traits>
2045 requires(!AT::propagate_on_container_copy_assignment::value ||
2046 AT::is_always_equal::value)
2047 constexpr small_vector_base& copy_assign(
2048 const small_vector_base<Allocator, I>& other) {
2049 return copy_assign_default(other);
2052 template <
unsigned I>
2053 constexpr void move_allocation_pointer(
2054 small_vector_base<alloc_ty, I>&& other)
noexcept {
2055 reset_data(other.data_ptr(), other.get_capacity(), other.get_size());
2056 other.set_default();
2059 template <
unsigned N = InlineCapacity>
2061 constexpr small_vector_base& move_assign_default(
2062 small_vector_base&& other)
noexcept {
2063 move_allocation_pointer(std::move(other));
2064 alloc_interface::operator=(std::move(other));
2068 template <
unsigned LessEqualI>
2069 requires(LessEqualI <= InlineCapacity)
2070 constexpr small_vector_base& move_assign_default(
2071 small_vector_base<Allocator, LessEqualI>&&
2072 other)
noexcept(std::is_nothrow_move_assignable_v<value_ty> &&
2073 std::is_nothrow_move_constructible_v<value_ty>) {
2077 if (InlineCapacity < other.get_capacity()) {
2078 move_allocation_pointer(std::move(other));
2081 if (InlineCapacity < get_capacity()) {
2083 if (std::is_constant_evaluated()) {
2084 new_data_ptr = other.allocate(InlineCapacity);
2086 new_data_ptr = storage_ptr();
2089 uninitialized_move(other.begin_ptr(), other.end_ptr(), new_data_ptr);
2090 destroy_range(begin_ptr(), end_ptr());
2091 deallocate(data_ptr(), get_capacity());
2092 set_data_ptr(new_data_ptr);
2093 set_capacity(InlineCapacity);
2094 }
else if (get_size() < other.get_size()) {
2097 ptr other_pivot = unchecked_next(other.begin_ptr(), get_size());
2098 std::move(other.begin_ptr(), other_pivot, begin_ptr());
2099 uninitialized_move(other_pivot, other.end_ptr(), end_ptr());
2104 std::move(other.begin_ptr(), other.end_ptr(), begin_ptr());
2105 destroy_range(new_end, end_ptr());
2108 set_size(other.get_size());
2116 alloc_interface::operator=(std::move(other));
2120 template <
unsigned GreaterI>
2121 requires(InlineCapacity < GreaterI)
2122 constexpr small_vector_base& move_assign_default(
2123 small_vector_base<Allocator, GreaterI>&& other) {
2124 if (other.has_allocation()) {
2125 move_allocation_pointer(std::move(other));
2126 }
else if (get_capacity() < other.get_size() ||
2127 (has_allocation() &&
2128 !(other.allocator_ref() == allocator_ref()))) {
2132 size_ty new_capacity =
2133 get_capacity() < other.get_size()
2134 ? unchecked_calculate_new_capacity(other.get_size())
2138 other.allocate_with_hint(new_capacity, other.allocation_end_ptr());
2141 uninitialized_move(other.begin_ptr(), other.end_ptr(), new_data_ptr);
2143 other.deallocate(new_data_ptr, new_capacity);
2147 reset_data(new_data_ptr, new_capacity, other.get_size());
2149 if (get_size() < other.get_size()) {
2152 ptr other_pivot = unchecked_next(other.begin_ptr(), get_size());
2153 std::move(other.begin_ptr(), other_pivot, begin_ptr());
2154 uninitialized_move(other_pivot, other.end_ptr(), end_ptr());
2159 std::move(other.begin_ptr(), other.end_ptr(), begin_ptr());
2160 destroy_range(new_end, end_ptr());
2164 set_size(other.get_size());
2167 alloc_interface::operator=(std::move(other));
2171 template <
unsigned I>
2172 constexpr small_vector_base& move_assign_unequal_no_propagate(
2173 small_vector_base<Allocator, I>&& other) {
2174 if (get_capacity() < other.get_size()) {
2176 size_ty new_capacity = unchecked_calculate_new_capacity(other.get_size());
2178 unchecked_allocate(new_capacity, other.allocation_end_ptr());
2181 uninitialized_move(other.begin_ptr(), other.end_ptr(), new_data_ptr);
2183 deallocate(new_data_ptr, new_capacity);
2187 reset_data(new_data_ptr, new_capacity, other.get_size());
2189 if (get_size() < other.get_size()) {
2192 ptr other_pivot = unchecked_next(other.begin_ptr(), get_size());
2193 std::move(other.begin_ptr(), other_pivot, begin_ptr());
2194 uninitialized_move(other_pivot, other.end_ptr(), end_ptr());
2199 std::move(other.begin_ptr(), other.end_ptr(), begin_ptr()),
2204 set_size(other.get_size());
2207 alloc_interface::operator=(std::move(other));
2211 template <
unsigned I,
typename A = alloc_ty>
2212 requires allocations_are_movable_v<A>
2213 constexpr small_vector_base&
2214 move_assign(small_vector_base<Allocator, I>&& other)
noexcept(
2215 noexcept(std::declval<small_vector_base&>().move_assign_default(
2216 std::move(other)))) {
2217 return move_assign_default(std::move(other));
2220 template <
unsigned I,
typename A = alloc_ty>
2221 requires(!allocations_are_movable_v<A>)
2222 constexpr small_vector_base& move_assign(
2223 small_vector_base<Allocator, I>&& other) {
2224 if (other.allocator_ref() == allocator_ref()) {
2225 return move_assign_default(std::move(other));
2227 return move_assign_unequal_no_propagate(std::move(other));
2230 template <
unsigned I = InlineCapacity>
2232 constexpr void move_initialize(small_vector_base&& other)
noexcept {
2233 set_data(other.data_ptr(), other.get_capacity(), other.get_size());
2234 other.set_default();
2237 template <
unsigned LessEqualI>
2238 requires(LessEqualI <= InlineCapacity)
2240 move_initialize(small_vector_base<Allocator, LessEqualI>&& other)
noexcept(
2241 std::is_nothrow_move_constructible_v<value_ty>) {
2242 if (InlineCapacity < other.get_capacity()) {
2243 set_data(other.data_ptr(), other.get_capacity(), other.get_size());
2244 other.set_default();
2246 set_to_inline_storage();
2247 uninitialized_move(other.begin_ptr(), other.end_ptr(), data_ptr());
2248 set_size(other.get_size());
2252 template <
unsigned GreaterI>
2253 requires(InlineCapacity < GreaterI)
2254 constexpr void move_initialize(
2255 small_vector_base<Allocator, GreaterI>&& other) {
2256 if (other.has_allocation()) {
2257 set_data(other.data_ptr(), other.get_capacity(), other.get_size());
2258 other.set_default();
2260 if (InlineCapacity < other.get_size()) {
2263 unchecked_allocate(other.get_size(), other.allocation_end_ptr()));
2264 set_capacity(other.get_size());
2267 uninitialized_move(other.begin_ptr(), other.end_ptr(), data_ptr());
2269 deallocate(data_ptr(), get_capacity());
2273 set_to_inline_storage();
2274 uninitialized_move(other.begin_ptr(), other.end_ptr(), data_ptr());
2277 set_size(other.get_size());
2282 small_vector_base(
const small_vector_base&) =
delete;
2283 small_vector_base(small_vector_base&&) noexcept = delete;
2284 small_vector_base& operator=(const small_vector_base&) = delete;
2285 small_vector_base& operator=(small_vector_base&&) noexcept = delete;
2287 constexpr small_vector_base() noexcept { set_default(); }
2292 template <
unsigned I,
typename... MaybeAlloc>
2293 constexpr small_vector_base(bypass_tag,
2294 const small_vector_base<Allocator, I>& other,
2295 const MaybeAlloc&... alloc)
2296 : alloc_interface(other, alloc...) {
2297 if (InlineCapacity < other.get_size()) {
2299 unchecked_allocate(other.get_size(), other.allocation_end_ptr()));
2300 set_capacity(other.get_size());
2303 uninitialized_copy(other.begin_ptr(), other.end_ptr(), data_ptr());
2305 deallocate(data_ptr(), get_capacity());
2309 set_to_inline_storage();
2310 uninitialized_copy(other.begin_ptr(), other.end_ptr(), data_ptr());
2313 set_size(other.get_size());
2316 template <
unsigned I>
2317 constexpr small_vector_base(
2319 small_vector_base<Allocator, I>&&
2320 other)
noexcept(std::is_nothrow_move_constructible_v<value_ty> ||
2321 (I == 0 && I == InlineCapacity))
2322 : alloc_interface(std::move(other)) {
2323 move_initialize(std::move(other));
2326 template <
unsigned I,
typename A = alloc_ty>
2327 requires std::same_as<A, std::allocator<value_ty>> ||
2328 std::allocator_traits<A>::is_always_equal::value
2329 constexpr small_vector_base(
2330 bypass_tag, small_vector_base<Allocator, I>&& other,
2331 const alloc_ty&)
noexcept(
noexcept(small_vector_base(bypass,
2333 : small_vector_base(bypass, std::move(other)) {}
2335 template <
unsigned I,
typename A = alloc_ty>
2336 requires(!(std::same_as<A, std::allocator<value_ty>> ||
2337 std::allocator_traits<A>::is_always_equal::value))
2338 constexpr small_vector_base(bypass_tag,
2339 small_vector_base<Allocator, I>&& other,
2340 const alloc_ty& alloc)
2341 : alloc_interface(alloc) {
2342 if (other.allocator_ref() == alloc) {
2343 move_initialize(std::move(other));
2347 if (InlineCapacity < other.get_size()) {
2350 unchecked_allocate(other.get_size(), other.allocation_end_ptr()));
2351 set_capacity(other.get_size());
2354 uninitialized_move(other.begin_ptr(), other.end_ptr(), data_ptr());
2356 deallocate(data_ptr(), get_capacity());
2360 set_to_inline_storage();
2361 uninitialized_move(other.begin_ptr(), other.end_ptr(), data_ptr());
2364 set_size(other.get_size());
2367 constexpr explicit small_vector_base(
const alloc_ty& alloc) noexcept
2368 : alloc_interface(alloc) {
2372 constexpr small_vector_base(size_ty count,
const alloc_ty& alloc)
2373 : alloc_interface(alloc) {
2374 if (InlineCapacity < count) {
2375 set_data_ptr(checked_allocate(count));
2376 set_capacity(count);
2378 set_to_inline_storage();
2382 uninitialized_value_construct(begin_ptr(),
2383 unchecked_next(begin_ptr(), count));
2385 if (has_allocation()) {
2386 deallocate(data_ptr(), get_capacity());
2393 constexpr small_vector_base(size_ty count,
const value_ty& val,
2394 const alloc_ty& alloc)
2395 : alloc_interface(alloc) {
2396 if (InlineCapacity < count) {
2397 set_data_ptr(checked_allocate(count));
2398 set_capacity(count);
2400 set_to_inline_storage();
2404 uninitialized_fill(begin_ptr(), unchecked_next(begin_ptr(), count), val);
2406 if (has_allocation()) {
2407 deallocate(data_ptr(), get_capacity());
2414 template <
typename Generator>
2415 constexpr small_vector_base(size_ty count, Generator& g,
2416 const alloc_ty& alloc)
2417 : alloc_interface(alloc) {
2418 if (InlineCapacity < count) {
2419 set_data_ptr(checked_allocate(count));
2420 set_capacity(count);
2422 set_to_inline_storage();
2425 ptr curr = begin_ptr();
2426 const ptr new_end = unchecked_next(begin_ptr(), count);
2428 for (; !(curr == new_end); ++curr) {
2429 construct(curr, g());
2432 destroy_range(begin_ptr(), curr);
2433 if (has_allocation()) {
2434 deallocate(data_ptr(), get_capacity());
2441 template <std::input_iterator InputIt>
2442 constexpr small_vector_base(InputIt first, InputIt last,
2443 std::input_iterator_tag,
const alloc_ty& alloc)
2444 : small_vector_base(alloc) {
2445 using iterator_cat =
2446 typename std::iterator_traits<InputIt>::iterator_category;
2447 append_range(first, last, iterator_cat{});
2450 template <std::forward_iterator ForwardIt>
2451 constexpr small_vector_base(ForwardIt first, ForwardIt last,
2452 std::forward_iterator_tag,
const alloc_ty& alloc)
2453 : alloc_interface(alloc) {
2454 size_ty count = external_range_length(first, last);
2455 if (InlineCapacity < count) {
2456 set_data_ptr(unchecked_allocate(count));
2457 set_capacity(count);
2459 uninitialized_copy(first, last, begin_ptr());
2461 deallocate(data_ptr(), get_capacity());
2465 set_to_inline_storage();
2466 uninitialized_copy(first, last, begin_ptr());
2472 constexpr ~small_vector_base() noexcept {
2473 assert(InlineCapacity <= get_capacity() &&
"Invalid capacity.");
2478 constexpr void set_to_inline_storage() {
2479 set_capacity(InlineCapacity);
2480 if (std::is_constant_evaluated()) {
2481 return set_data_ptr(alloc_interface::allocate(InlineCapacity));
2483 set_data_ptr(storage_ptr());
2486 constexpr void assign_with_copies(size_ty count,
const value_ty& val) {
2487 if (get_capacity() < count) {
2488 size_ty new_capacity = checked_calculate_new_capacity(count);
2489 ptr new_begin = unchecked_allocate(new_capacity);
2492 uninitialized_fill(new_begin, unchecked_next(new_begin, count), val);
2494 deallocate(new_begin, new_capacity);
2498 reset_data(new_begin, new_capacity, count);
2499 }
else if (get_size() < count) {
2500 std::fill(begin_ptr(), end_ptr(), val);
2501 uninitialized_fill(end_ptr(), unchecked_next(begin_ptr(), count), val);
2504 erase_range(std::fill_n(begin_ptr(), count, val), end_ptr());
2508 template <
typename InputIt>
2509 requires std::is_assignable_v<value_ty&, decltype(*std::declval<InputIt>())>
2510 constexpr void assign_with_range(InputIt first, InputIt last,
2511 std::input_iterator_tag) {
2512 using iterator_cat =
2513 typename std::iterator_traits<InputIt>::iterator_category;
2515 ptr curr = begin_ptr();
2516 for (; !(end_ptr() == curr || first == last);
2517 ++curr,
static_cast<void>(++first)) {
2521 if (first == last) {
2524 append_range(first, last, iterator_cat{});
2528 template <
typename ForwardIt>
2529 requires std::is_assignable_v<value_ty&,
2530 decltype(*std::declval<ForwardIt>())>
2531 constexpr void assign_with_range(ForwardIt first, ForwardIt last,
2532 std::forward_iterator_tag) {
2533 const size_ty count = external_range_length(first, last);
2534 if (get_capacity() < count) {
2535 size_ty new_capacity = checked_calculate_new_capacity(count);
2536 ptr new_begin = unchecked_allocate(new_capacity);
2539 uninitialized_copy(first, last, new_begin);
2541 deallocate(new_begin, new_capacity);
2545 reset_data(new_begin, new_capacity, count);
2546 }
else if (get_size() < count) {
2547 ForwardIt pivot = copy_n_return_in(first, get_size(), begin_ptr());
2548 uninitialized_copy(pivot, last, end_ptr());
2551 erase_range(copy_range(first, last, begin_ptr()), end_ptr());
2555 template <
typename InputIt>
2557 !std::is_assignable_v<value_ty&, decltype(*std::declval<InputIt>())>)
2558 constexpr void assign_with_range(InputIt first, InputIt last,
2559 std::input_iterator_tag) {
2560 using iterator_cat =
2561 typename std::iterator_traits<InputIt>::iterator_category;
2565 append_range(first, last, iterator_cat{});
2571 template <
typename Policy =
void,
typename V = value_ty>
2572 requires is_explicitly_move_insertable_v<V> &&
2573 (!std::same_as<Policy, strong_exception_policy> ||
2574 relocate_with_move_v<V>)
2575 constexpr ptr uninitialized_move(ptr first, ptr last, ptr d_first)
noexcept(
2576 std::is_nothrow_move_constructible_v<value_ty>) {
2577 return uninitialized_copy(std::make_move_iterator(first),
2578 std::make_move_iterator(last), d_first);
2581 template <
typename Policy =
void,
typename V = value_ty>
2582 requires(!is_explicitly_move_insertable_v<V> ||
2583 (std::same_as<Policy, strong_exception_policy> &&
2584 !relocate_with_move_v<V>))
2585 constexpr ptr uninitialized_move(ptr first, ptr last, ptr d_first) noexcept(
2586 alloc_interface::template is_uninitialized_memcpyable_iterator_v<ptr>) {
2587 return uninitialized_copy(first, last, d_first);
2590 constexpr ptr shift_into_uninitialized(ptr pos, size_ty n_shift) {
2594 assert(n_shift != 0 &&
"The value of `n_shift` should not be 0.");
2596 const ptr original_end = end_ptr();
2597 const ptr pivot = unchecked_prev(original_end, n_shift);
2599 uninitialized_move(pivot, original_end, original_end);
2600 increase_size(n_shift);
2601 return move_right(pos, pivot, original_end);
2604 template <
typename... Args>
2605 constexpr ptr append_element(Args&&... args) {
2606 if (get_size() < get_capacity()) {
2607 return emplace_into_current_end(std::forward<Args>(args)...);
2609 return emplace_into_reallocation_end(std::forward<Args>(args)...);
2612 constexpr ptr append_copies(size_ty count,
const value_ty& val) {
2613 if (num_uninitialized() < count) {
2615 if (get_max_size() - get_size() < count) {
2616 throw_allocation_size_error();
2619 size_ty original_size = get_size();
2620 size_ty new_size = get_size() + count;
2623 size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
2624 ptr new_data_ptr = unchecked_allocate(new_capacity, allocation_end_ptr());
2625 ptr new_last = unchecked_next(new_data_ptr, original_size);
2629 uninitialized_fill(new_last, unchecked_next(new_last, count), val);
2630 uninitialized_move(begin_ptr(), end_ptr(), new_data_ptr);
2632 destroy_range(unchecked_next(new_data_ptr, original_size), new_last);
2633 deallocate(new_data_ptr, new_capacity);
2637 reset_data(new_data_ptr, new_capacity, new_size);
2638 return unchecked_next(new_data_ptr, original_size);
2640 const ptr ret = end_ptr();
2641 uninitialized_fill(ret, unchecked_next(ret, count), val);
2642 increase_size(count);
2647 template <std::same_as<strong_exception_policy> MovePolicy,
typename InputIt>
2648 constexpr ptr append_range(InputIt first, InputIt last,
2649 std::input_iterator_tag) {
2651 size_ty original_size = get_size();
2652 for (; !(first == last); ++first) {
2654 append_element(*first);
2656 erase_range(unchecked_next(begin_ptr(), original_size), end_ptr());
2660 return unchecked_next(begin_ptr(), original_size);
2663 template <
typename MovePolicy =
void,
typename InputIt>
2664 requires(!std::same_as<MovePolicy, strong_exception_policy>)
2665 constexpr ptr append_range(InputIt first, InputIt last,
2666 std::input_iterator_tag) {
2667 size_ty original_size = get_size();
2668 for (; !(first == last); ++first) {
2669 append_element(*first);
2671 return unchecked_next(begin_ptr(), original_size);
2674 template <
typename MovePolicy =
void,
typename ForwardIt>
2675 constexpr ptr append_range(ForwardIt first, ForwardIt last,
2676 std::forward_iterator_tag) {
2677 const size_ty num_insert = external_range_length(first, last);
2679 if (num_uninitialized() < num_insert) {
2681 if (get_max_size() - get_size() < num_insert) {
2682 throw_allocation_size_error();
2685 size_ty original_size = get_size();
2686 size_ty new_size = get_size() + num_insert;
2689 size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
2690 ptr new_data_ptr = unchecked_allocate(new_capacity, allocation_end_ptr());
2691 ptr new_last = unchecked_next(new_data_ptr, original_size);
2694 new_last = uninitialized_copy(first, last, new_last);
2695 uninitialized_move<MovePolicy>(begin_ptr(), end_ptr(), new_data_ptr);
2697 destroy_range(unchecked_next(new_data_ptr, original_size), new_last);
2698 deallocate(new_data_ptr, new_capacity);
2702 reset_data(new_data_ptr, new_capacity, new_size);
2703 return unchecked_next(new_data_ptr, original_size);
2705 ptr ret = end_ptr();
2706 uninitialized_copy(first, last, ret);
2707 increase_size(num_insert);
2712 template <
typename... Args>
2713 constexpr ptr emplace_at(ptr pos, Args&&... args) {
2714 assert(get_size() <= get_capacity() &&
"size was greater than capacity");
2716 if (get_size() < get_capacity()) {
2717 return emplace_into_current(pos, std::forward<Args>(args)...);
2719 return emplace_into_reallocation(pos, std::forward<Args>(args)...);
2722 constexpr ptr insert_copies(ptr pos, size_ty count,
const value_ty& val) {
2727 if (end_ptr() == pos) {
2729 return append_element(val);
2731 return append_copies(count, val);
2734 if (num_uninitialized() < count) {
2736 if (get_max_size() - get_size() < count) {
2737 throw_allocation_size_error();
2740 const size_ty offset = internal_range_length(begin_ptr(), pos);
2742 const size_ty new_size = get_size() + count;
2745 const size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
2746 ptr new_data_ptr = unchecked_allocate(new_capacity, allocation_end_ptr());
2747 ptr new_first = unchecked_next(new_data_ptr, offset);
2748 ptr new_last = new_first;
2751 uninitialized_fill(new_first, unchecked_next(new_first, count), val);
2752 unchecked_advance(new_last, count);
2754 uninitialized_move(begin_ptr(), pos, new_data_ptr);
2755 new_first = new_data_ptr;
2756 uninitialized_move(pos, end_ptr(), new_last);
2758 destroy_range(new_first, new_last);
2759 deallocate(new_data_ptr, new_capacity);
2763 reset_data(new_data_ptr, new_capacity, new_size);
2764 return unchecked_next(begin_ptr(), offset);
2769 const size_ty tail_size = internal_range_length(pos, end_ptr());
2770 if (tail_size < count) {
2779 ptr original_end = end_ptr();
2782 size_ty num_val_tail = count - tail_size;
2784 if (std::is_constant_evaluated()) {
2785 uninitialized_fill(end_ptr(), unchecked_next(end_ptr(), num_val_tail),
2787 increase_size(num_val_tail);
2789 const heap_temporary tmp(*
this, val);
2791 uninitialized_move(pos, original_end, end_ptr());
2792 increase_size(tail_size);
2794 std::fill_n(pos, tail_size, tmp.get());
2799 uninitialized_fill(end_ptr(), unchecked_next(end_ptr(), num_val_tail),
2801 increase_size(num_val_tail);
2805 const stack_temporary tmp(*
this, val);
2808 uninitialized_move(pos, original_end, end_ptr());
2809 increase_size(tail_size);
2813 std::fill_n(pos, tail_size, tmp.get());
2816 ptr inserted_end = unchecked_prev(end_ptr(), tail_size);
2817 move_left(inserted_end, end_ptr(), pos);
2818 destroy_range(inserted_end, end_ptr());
2819 decrease_size(tail_size);
2824 destroy_range(original_end, end_ptr());
2825 decrease_size(internal_range_length(original_end, end_ptr()));
2829 if (std::is_constant_evaluated()) {
2830 const heap_temporary tmp(*
this, val);
2832 ptr inserted_end = shift_into_uninitialized(pos, count);
2833 std::fill(pos, inserted_end, tmp.get());
2837 const stack_temporary tmp(*
this, val);
2839 ptr inserted_end = shift_into_uninitialized(pos, count);
2844 std::fill(pos, inserted_end, tmp.get());
2846 ptr original_end = move_left(inserted_end, end_ptr(), pos);
2847 destroy_range(original_end, end_ptr());
2848 decrease_size(count);
2856 template <
typename ForwardIt>
2857 constexpr ptr insert_range_helper(ptr pos, ForwardIt first, ForwardIt last) {
2858 assert(!(first == last) &&
"The range should not be empty.");
2859 assert(!(end_ptr() == pos) &&
"`pos` should not be at the end.");
2861 const size_ty num_insert = external_range_length(first, last);
2862 if (num_uninitialized() < num_insert) {
2864 if (get_max_size() - get_size() < num_insert) {
2865 throw_allocation_size_error();
2868 const size_ty offset = internal_range_length(begin_ptr(), pos);
2869 const size_ty new_size = get_size() + num_insert;
2872 const size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
2873 const ptr new_data_ptr =
2874 unchecked_allocate(new_capacity, allocation_end_ptr());
2875 ptr new_first = unchecked_next(new_data_ptr, offset);
2876 ptr new_last = new_first;
2879 uninitialized_copy(first, last, new_first);
2880 unchecked_advance(new_last, num_insert);
2882 uninitialized_move(begin_ptr(), pos, new_data_ptr);
2883 new_first = new_data_ptr;
2884 uninitialized_move(pos, end_ptr(), new_last);
2886 destroy_range(new_first, new_last);
2887 deallocate(new_data_ptr, new_capacity);
2891 reset_data(new_data_ptr, new_capacity, new_size);
2892 return unchecked_next(begin_ptr(), offset);
2896 const size_ty tail_size = internal_range_length(pos, end_ptr());
2897 if (tail_size < num_insert) {
2899 ptr original_end = end_ptr();
2900 ForwardIt pivot = unchecked_next(first, tail_size);
2903 uninitialized_copy(pivot, last, end_ptr());
2904 increase_size(num_insert - tail_size);
2908 uninitialized_move(pos, original_end, end_ptr());
2909 increase_size(tail_size);
2913 copy_range(first, pivot, pos);
2916 ptr inserted_end = unchecked_prev(end_ptr(), tail_size);
2917 move_left(inserted_end, end_ptr(), pos);
2918 destroy_range(inserted_end, end_ptr());
2919 decrease_size(tail_size);
2924 destroy_range(original_end, end_ptr());
2925 decrease_size(internal_range_length(original_end, end_ptr()));
2929 shift_into_uninitialized(pos, num_insert);
2934 copy_range(first, last, pos);
2936 ptr inserted_end = unchecked_next(pos, num_insert);
2937 ptr original_end = move_left(inserted_end, end_ptr(), pos);
2938 destroy_range(original_end, end_ptr());
2939 decrease_size(num_insert);
2947 template <
typename InputIt>
2948 constexpr ptr insert_range(ptr pos, InputIt first, InputIt last,
2949 std::input_iterator_tag) {
2950 assert(!(first == last) &&
"The range should not be empty.");
2954 if (end_ptr() == pos) {
2955 return append_range(first, last, std::input_iterator_tag{});
2958 using iterator_cat =
2959 typename std::iterator_traits<InputIt>::iterator_category;
2960 small_vector_base tmp(first, last, iterator_cat{}, allocator_ref());
2962 return insert_range_helper(pos, std::make_move_iterator(tmp.begin_ptr()),
2963 std::make_move_iterator(tmp.end_ptr()));
2966 template <
typename ForwardIt>
2967 constexpr ptr insert_range(ptr pos, ForwardIt first, ForwardIt last,
2968 std::forward_iterator_tag) {
2969 if (!(end_ptr() == pos)) {
2970 return insert_range_helper(pos, first, last);
2973 if (unchecked_next(first) == last) {
2974 return append_element(*first);
2977 using iterator_cat =
2978 typename std::iterator_traits<ForwardIt>::iterator_category;
2979 return append_range(first, last, iterator_cat{});
2982 template <
typename... Args>
2983 constexpr ptr emplace_into_current_end(Args&&... args) {
2984 construct(end_ptr(), std::forward<Args>(args)...);
2986 return unchecked_prev(end_ptr());
2989 template <
typename V = value_ty>
2990 requires std::is_nothrow_move_constructible_v<V>
2991 constexpr ptr emplace_into_current(ptr pos, value_ty&& val) {
2992 if (pos == end_ptr()) {
2993 return emplace_into_current_end(std::move(val));
2999 shift_into_uninitialized(pos, 1);
3001 construct(pos, std::move(val));
3005 template <
typename... Args>
3006 constexpr ptr emplace_into_current(ptr pos, Args&&... args) {
3007 if (pos == end_ptr()) {
3008 return emplace_into_current_end(std::forward<Args>(args)...);
3011 if (std::is_constant_evaluated()) {
3012 heap_temporary tmp(*
this, std::forward<Args>(args)...);
3013 shift_into_uninitialized(pos, 1);
3014 *pos = tmp.release();
3019 stack_temporary tmp(*
this, std::forward<Args>(args)...);
3020 shift_into_uninitialized(pos, 1);
3021 *pos = tmp.release();
3025 template <
typename... Args>
3026 constexpr ptr emplace_into_reallocation_end(Args&&... args) {
3028 if (get_max_size() == get_size()) {
3029 throw_allocation_size_error();
3032 const size_ty new_size = get_size() + 1;
3035 const size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
3036 const ptr new_data_ptr =
3037 unchecked_allocate(new_capacity, allocation_end_ptr());
3038 const ptr emplace_pos = unchecked_next(new_data_ptr, get_size());
3041 construct(emplace_pos, std::forward<Args>(args)...);
3043 uninitialized_move<strong_exception_policy>(begin_ptr(), end_ptr(),
3046 destroy(emplace_pos);
3050 deallocate(new_data_ptr, new_capacity);
3054 reset_data(new_data_ptr, new_capacity, new_size);
3058 template <
typename... Args>
3059 constexpr ptr emplace_into_reallocation(ptr pos, Args&&... args) {
3060 const size_ty offset = internal_range_length(begin_ptr(), pos);
3061 if (offset == get_size()) {
3062 return emplace_into_reallocation_end(std::forward<Args>(args)...);
3065 if (get_max_size() == get_size()) {
3066 throw_allocation_size_error();
3069 const size_ty new_size = get_size() + 1;
3072 const size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
3073 const ptr new_data_ptr =
3074 unchecked_allocate(new_capacity, allocation_end_ptr());
3075 ptr new_first = unchecked_next(new_data_ptr, offset);
3076 ptr new_last = new_first;
3079 construct(new_first, std::forward<Args>(args)...);
3080 unchecked_advance(new_last, 1);
3082 uninitialized_move(begin_ptr(), pos, new_data_ptr);
3083 new_first = new_data_ptr;
3084 uninitialized_move(pos, end_ptr(), new_last);
3086 destroy_range(new_first, new_last);
3087 deallocate(new_data_ptr, new_capacity);
3091 reset_data(new_data_ptr, new_capacity, new_size);
3092 return unchecked_next(begin_ptr(), offset);
3095 constexpr ptr shrink_to_size() {
3096 if (!has_allocation() || get_size() == get_capacity()) {
3102 size_ty new_capacity;
3105 if (InlineCapacity < get_size()) {
3106 new_capacity = get_size();
3107 new_data_ptr = unchecked_allocate(new_capacity, allocation_end_ptr());
3110 new_capacity = InlineCapacity;
3111 if (std::is_constant_evaluated()) {
3112 new_data_ptr = alloc_interface::allocate(InlineCapacity);
3114 new_data_ptr = storage_ptr();
3118 uninitialized_move(begin_ptr(), end_ptr(), new_data_ptr);
3120 destroy_range(begin_ptr(), end_ptr());
3121 deallocate(data_ptr(), get_capacity());
3123 set_data_ptr(new_data_ptr);
3124 set_capacity(new_capacity);
3129 template <
typename... ValueT>
3130 constexpr void resize_with(size_ty new_size,
const ValueT&... val) {
3133 if (new_size == 0) {
3137 if (get_capacity() < new_size) {
3140 if (get_max_size() < new_size) {
3141 throw_allocation_size_error();
3144 const size_ty original_size = get_size();
3147 const size_ty new_capacity = unchecked_calculate_new_capacity(new_size);
3148 ptr new_data_ptr = unchecked_allocate(new_capacity, allocation_end_ptr());
3149 ptr new_last = unchecked_next(new_data_ptr, original_size);
3152 new_last = uninitialized_fill(
3153 new_last, unchecked_next(new_data_ptr, new_size), val...);
3156 uninitialized_move<strong_exception_policy>(begin_ptr(), end_ptr(),
3159 destroy_range(unchecked_next(new_data_ptr, original_size), new_last);
3160 deallocate(new_data_ptr, new_capacity);
3164 reset_data(new_data_ptr, new_capacity, new_size);
3165 }
else if (get_size() < new_size) {
3167 uninitialized_fill(end_ptr(), unchecked_next(begin_ptr(), new_size),
3171 erase_range(unchecked_next(begin_ptr(), new_size), end_ptr());
3177 constexpr void request_capacity(size_ty request) {
3178 if (request <= get_capacity()) {
3182 size_ty new_capacity = checked_calculate_new_capacity(request);
3183 ptr new_begin = unchecked_allocate(new_capacity);
3186 uninitialized_move<strong_exception_policy>(begin_ptr(), end_ptr(),
3189 deallocate(new_begin, new_capacity);
3195 set_data_ptr(new_begin);
3196 set_capacity(new_capacity);
3199 constexpr ptr erase_at(ptr pos) {
3200 move_left(unchecked_next(pos), end_ptr(), pos);
3205 constexpr void erase_last() {
3212 constexpr ptr erase_range(ptr first, ptr last) {
3213 if (!(first == last)) {
3214 erase_to_end(move_left(last, end_ptr(), first));
3219 constexpr void erase_to_end(ptr pos) {
3220 assert(0 <= (end_ptr() - pos) &&
"`pos` was in the uninitialized range");
3221 if (size_ty change = internal_range_length(pos, end_ptr())) {
3222 decrease_size(change);
3223 destroy_range(pos, unchecked_next(pos, change));
3227 constexpr void erase_all() {
3228 ptr curr_end = end_ptr();
3230 destroy_range(begin_ptr(), curr_end);
3233 constexpr void swap_elements(small_vector_base& other)
noexcept(
3234 std::is_nothrow_move_constructible_v<value_ty> &&
3235 std::is_nothrow_swappable_v<value_ty>) {
3236 assert(get_size() <= other.get_size());
3238 const ptr other_tail =
3239 std::swap_ranges(begin_ptr(), end_ptr(), other.begin_ptr());
3240 uninitialized_move(other_tail, other.end_ptr(), end_ptr());
3241 destroy_range(other_tail, other.end_ptr());
3246 constexpr void swap_default(small_vector_base& other)
noexcept(
3247 std::is_nothrow_move_constructible_v<value_ty> &&
3248 std::is_nothrow_swappable_v<value_ty>) {
3259 assert(get_capacity() <= other.get_capacity());
3261 if (has_allocation()) {
3262 swap_allocation(other);
3263 }
else if (other.has_allocation()) {
3266 uninitialized_move(begin_ptr(), end_ptr(), other.storage_ptr());
3267 destroy_range(begin_ptr(), end_ptr());
3269 set_data_ptr(other.data_ptr());
3270 set_capacity(other.get_capacity());
3272 other.set_data_ptr(other.storage_ptr());
3273 other.set_capacity(InlineCapacity);
3276 }
else if (get_size() < other.get_size()) {
3277 swap_elements(other);
3279 other.swap_elements(*
this);
3282 alloc_interface::swap(other);
3285 constexpr void swap_unequal_no_propagate(small_vector_base& other) {
3286 assert(get_capacity() <= other.get_capacity());
3288 if (get_capacity() < other.get_size()) {
3291 const size_ty new_capacity =
3292 unchecked_calculate_new_capacity(other.get_size());
3293 const ptr new_data_ptr = unchecked_allocate(new_capacity, end_ptr());
3296 uninitialized_move(other.begin_ptr(), other.end_ptr(), new_data_ptr);
3298 destroy_range(std::move(begin_ptr(), end_ptr(), other.begin_ptr()),
3301 destroy_range(new_data_ptr,
3302 unchecked_next(new_data_ptr, other.get_size()));
3306 deallocate(new_data_ptr, new_capacity);
3310 destroy_range(begin_ptr(), end_ptr());
3311 if (has_allocation()) {
3312 deallocate(data_ptr(), get_capacity());
3315 set_data_ptr(new_data_ptr);
3316 set_capacity(new_capacity);
3318 }
else if (get_size() < other.get_size()) {
3319 swap_elements(other);
3321 other.swap_elements(*
this);
3325 alloc_interface::swap(other);
3328 template <
typename A = alloc_ty>
3329 requires allocations_are_swappable_v<A> && (InlineCapacity == 0)
3330 constexpr void swap(small_vector_base& other)
noexcept {
3331 swap_allocation(other);
3332 alloc_interface::swap(other);
3335 template <
typename A = alloc_ty>
3336 requires allocations_are_swappable_v<A> && (InlineCapacity != 0)
3337 constexpr void swap(small_vector_base& other)
noexcept(
3338 std::is_nothrow_move_constructible_v<value_ty> &&
3339 std::is_nothrow_swappable_v<value_ty>) {
3340 if (get_capacity() < other.get_capacity()) {
3341 swap_default(other);
3343 other.swap_default(*
this);
3347 template <
typename A = alloc_ty>
3348 requires(!allocations_are_swappable_v<A>)
3349 constexpr void swap(small_vector_base& other) {
3350 if (get_capacity() < other.get_capacity()) {
3351 if (other.allocator_ref() == allocator_ref()) {
3352 swap_default(other);
3354 swap_unequal_no_propagate(other);
3357 if (other.allocator_ref() == allocator_ref()) {
3358 other.swap_default(*
this);
3360 other.swap_unequal_no_propagate(*
this);
3370 template <
typename InputIt>
3371 static constexpr InputIt unmove_iterator(InputIt it) {
3375 template <
typename InputIt>
3376 static constexpr auto unmove_iterator(std::move_iterator<InputIt> it)
3377 ->
decltype(unmove_iterator(it.base())) {
3378 return unmove_iterator(it.base());
3381 template <
typename InputIt>
3382 static constexpr auto unmove_iterator(std::reverse_iterator<InputIt> it)
3383 -> std::reverse_iterator<
decltype(unmove_iterator(it.base()))> {
3384 return std::reverse_iterator<
decltype(unmove_iterator(it.base()))>(
3385 unmove_iterator(it.base()));
3390 template <
typename InputIt>
3391 constexpr ptr copy_range(InputIt first, InputIt last, ptr dest) {
3393 if (std::is_constant_evaluated()) {
3394 if constexpr (!std::is_same_v<
decltype(unmove_iterator(
3395 std::declval<InputIt>())),
3397 return std::move(unmove_iterator(first), unmove_iterator(last), dest);
3402 return std::copy(first, last, dest);
3405 template <
typename InputIt>
3406 requires is_memcpyable_iterator_v<InputIt>
3407 constexpr InputIt copy_n_return_in(InputIt first, size_ty count,
3408 ptr dest)
noexcept {
3409 if (std::is_constant_evaluated()) {
3410 std::copy_n(first, count, dest);
3411 return unchecked_next(first, count);
3415 std::memcpy(to_address(dest), to_address(first),
3416 count *
sizeof(value_ty));
3420 return unchecked_next(first, count);
3423 template <
typename InputIt>
3424 requires is_memcpyable_iterator_v<InputIt>
3425 constexpr std::move_iterator<InputIt> copy_n_return_in(
3426 std::move_iterator<InputIt> first, size_ty count, ptr dest)
noexcept {
3427 return std::move_iterator<InputIt>(
3428 copy_n_return_in(first.base(), count, dest));
3431 template <
typename RandomIt>
3432 requires(!is_memcpyable_iterator_v<RandomIt> &&
3434 std::random_access_iterator_tag,
3435 typename std::iterator_traits<RandomIt>::iterator_category>)
3436 constexpr RandomIt copy_n_return_in(RandomIt first, size_ty count, ptr dest) {
3438 if (std::is_constant_evaluated()) {
3439 if constexpr (!std::is_same_v<
decltype(unmove_iterator(
3440 std::declval<RandomIt>())),
3442 auto bfirst = unmove_iterator(first);
3443 auto blast = unchecked_next(bfirst, count);
3444 std::move(bfirst, blast, dest);
3445 return unchecked_next(first, count);
3450 std::copy_n(first, count, dest);
3452 return unchecked_next(first, count);
3455 template <
typename InputIt>
3456 requires(!is_memcpyable_iterator_v<InputIt> &&
3458 std::random_access_iterator_tag,
3459 typename std::iterator_traits<InputIt>::iterator_category>)
3460 constexpr InputIt copy_n_return_in(InputIt first, size_ty count, ptr dest) {
3462 --count,
static_cast<void>(++dest),
static_cast<void>(++first)) {
3468 template <
typename V = value_ty>
3469 requires is_memcpyable_v<V>
3470 constexpr ptr move_left(ptr first, ptr last, ptr d_first) {
3473 if (std::is_constant_evaluated()) {
3474 return std::move(first, last, d_first);
3477 const size_ty num_moved = internal_range_length(first, last);
3478 if (num_moved != 0) {
3479 std::memmove(to_address(d_first), to_address(first),
3480 num_moved *
sizeof(value_ty));
3482 return unchecked_next(d_first, num_moved);
3485 template <
typename V = value_ty>
3486 requires(!is_memcpyable_v<V>)
3487 constexpr ptr move_left(ptr first, ptr last, ptr d_first) {
3489 return std::move(first, last, d_first);
3492 template <
typename V = value_ty>
3493 requires is_memcpyable_v<V>
3494 constexpr ptr move_right(ptr first, ptr last, ptr d_last) {
3497 if (std::is_constant_evaluated()) {
3498 return std::move_backward(first, last, d_last);
3501 const size_ty num_moved = internal_range_length(first, last);
3502 const ptr dest = unchecked_prev(d_last, num_moved);
3503 if (num_moved != 0) {
3504 std::memmove(to_address(dest), to_address(first),
3505 num_moved *
sizeof(value_ty));
3510 template <
typename V = value_ty>
3511 requires(!is_memcpyable_v<V>)
3512 constexpr ptr move_right(ptr first, ptr last, ptr d_last) {
3515 return std::move_backward(first, last, d_last);
3519 constexpr void set_default() {
3520 set_to_inline_storage();
3525 constexpr ptr data_ptr() noexcept {
3526 return m_data.data_ptr();
3530 constexpr cptr data_ptr() const noexcept {
3531 return m_data.data_ptr();
3535 constexpr size_ty get_capacity() const noexcept {
3536 return m_data.capacity();
3540 constexpr size_ty get_size() const noexcept {
3541 return m_data.size();
3545 constexpr size_ty num_uninitialized() const noexcept {
3546 return get_capacity() - get_size();
3550 constexpr ptr begin_ptr() noexcept {
3555 constexpr cptr begin_ptr() const noexcept {
3560 constexpr ptr end_ptr() noexcept {
3561 return unchecked_next(begin_ptr(), get_size());
3565 constexpr cptr end_ptr() const noexcept {
3566 return unchecked_next(begin_ptr(), get_size());
3570 constexpr ptr allocation_end_ptr() noexcept {
3571 return unchecked_next(begin_ptr(), get_capacity());
3575 constexpr cptr allocation_end_ptr() const noexcept {
3576 return unchecked_next(begin_ptr(), get_capacity());
3580 constexpr alloc_ty copy_allocator() const noexcept {
3581 return alloc_ty(allocator_ref());
3585 constexpr ptr storage_ptr() noexcept {
3586 return m_data.storage();
3590 constexpr cptr storage_ptr() const noexcept {
3591 return m_data.storage();
3595 constexpr bool has_allocation() const noexcept {
3596 if (std::is_constant_evaluated()) {
3599 return InlineCapacity < get_capacity();
3603 constexpr bool is_inlinable() const noexcept {
3604 return get_size() <= InlineCapacity;
3608 small_vector_data<ptr, size_type, value_ty, InlineCapacity> m_data;
3613template <
typename T,
unsigned InlineCapacity,
typename Allocator>
3614 requires concepts::small_vector::AllocatorFor<Allocator, T>
3616 :
private detail::small_vector_base<Allocator, InlineCapacity> {
3617 using base = detail::small_vector_base<Allocator, InlineCapacity>;
3620 static_assert(std::is_same_v<T, typename Allocator::value_type>,
3621 "`Allocator::value_type` must be the same as `T`.");
3623 template <
typename SameT,
unsigned DifferentInlineCapacity,
3624 typename SameAllocator>
3634 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
3636 typename std::allocator_traits<allocator_type>::const_pointer;
3643 static_assert(InlineCapacity <= (std::numeric_limits<size_type>::max)(),
3644 "InlineCapacity must be less than or equal to the maximum "
3645 "value of size_type.");
3647 static constexpr unsigned inline_capacity_v = InlineCapacity;
3650 static constexpr bool Destructible =
3653 static constexpr bool MoveAssignable =
3656 static constexpr bool CopyAssignable =
3659 static constexpr bool MoveConstructible =
3662 static constexpr bool CopyConstructible =
3665 static constexpr bool Swappable =
3668 static constexpr bool DefaultInsertable =
3672 static constexpr bool MoveInsertable =
3676 static constexpr bool CopyInsertable =
3680 static constexpr bool Erasable =
3684 template <
typename... Args>
3685 struct EmplaceConstructible {
3686 static constexpr bool value =
3697 requires CopyInsertable
3698 : base(base::bypass, other) {}
3701 std::is_nothrow_move_constructible_v<value_type> || InlineCapacity == 0)
3702 requires MoveInsertable
3703 : base(base::bypass, std::move(other)) {}
3709 requires CopyInsertable
3710 : base(base::bypass, other, alloc) {}
3713 requires MoveInsertable
3714 : base(base::bypass, std::move(other), alloc) {}
3718 requires DefaultInsertable
3719 : base(count, alloc) {}
3723 requires CopyInsertable
3724 : base(count, value, alloc) {}
3726 template <
typename Generator>
3727 requires std::invocable<Generator&> &&
3728 EmplaceConstructible<std::invoke_result_t<Generator&>>::value
3731 : base(count, g, alloc) {}
3733 template <std::input_iterator InputIt>
3734 requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value &&
3735 (std::forward_iterator<InputIt> || MoveInsertable)
3739 typename std::iterator_traits<InputIt>::iterator_category{},
3747 template <
unsigned I>
3748 requires CopyInsertable
3750 : base(base::bypass, other) {}
3752 template <
unsigned I>
3753 requires MoveInsertable
3756 other)
noexcept(std::is_nothrow_move_constructible<value_type>::
3759 : base(base::bypass, std::move(other)) {}
3761 template <
unsigned I>
3762 requires CopyInsertable
3765 : base(base::bypass, other, alloc) {}
3767 template <
unsigned I>
3768 requires MoveInsertable
3771 : base(base::bypass, std::move(other), alloc) {}
3778 requires CopyInsertable && CopyAssignable
3785 (std::is_same_v<std::allocator<value_type>, Allocator> ||
3786 std::allocator_traits<
3787 Allocator>::propagate_on_container_move_assignment::value ||
3788 std::allocator_traits<Allocator>::is_always_equal::value) &&
3789 ((std::is_nothrow_move_assignable_v<value_type> &&
3790 std::is_nothrow_move_constructible_v<value_type>) ||
3791 InlineCapacity == 0))
3796 requires MoveInsertable && MoveAssignable
3798 assign(std::move(other));
3803 requires CopyInsertable && CopyAssignable
3810 requires CopyInsertable && CopyAssignable
3812 base::assign_with_copies(count, value);
3815 template <std::input_iterator InputIt>
3816 requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value &&
3817 (std::forward_iterator<InputIt> || MoveInsertable)
3818 constexpr void assign(InputIt first, InputIt last) {
3819 using iterator_cat =
3820 typename std::iterator_traits<InputIt>::iterator_category;
3821 base::assign_with_range(first, last, iterator_cat{});
3824 constexpr void assign(std::initializer_list<value_type> ilist)
3825 requires EmplaceConstructible<const_reference>::value
3827 assign(ilist.begin(), ilist.end());
3831 requires CopyInsertable && CopyAssignable
3833 if (&other !=
this) {
3834 base::copy_assign(other);
3838 template <
unsigned I>
3839 requires CopyInsertable && CopyAssignable
3840 constexpr void assign(
const small_vector<T, I, Allocator>& other) {
3841 base::copy_assign(other);
3845 (std::is_same_v<std::allocator<value_type>, Allocator> ||
3846 std::allocator_traits<
3847 Allocator>::propagate_on_container_move_assignment::value ||
3848 std::allocator_traits<Allocator>::is_always_equal::value) &&
3849 ((std::is_nothrow_move_assignable_v<value_type> &&
3850 std::is_nothrow_move_constructible_v<value_type>) ||
3851 InlineCapacity == 0))
3852 requires MoveInsertable && MoveAssignable
3854 if (&other !=
this) {
3855 base::move_assign(std::move(other));
3859 template <
unsigned I>
3860 requires MoveInsertable && MoveAssignable
3862 I <= InlineCapacity &&
3863 (std::is_same_v<std::allocator<value_type>, Allocator> ||
3864 std::allocator_traits<
3865 Allocator>::propagate_on_container_move_assignment::value ||
3866 std::allocator_traits<Allocator>::is_always_equal::value) &&
3867 std::is_nothrow_move_assignable_v<value_type> &&
3868 std::is_nothrow_move_constructible_v<value_type>) {
3869 base::move_assign(std::move(other));
3873 (std::is_same_v<std::allocator<value_type>, Allocator> ||
3874 std::allocator_traits<Allocator>::propagate_on_container_swap::value ||
3875 std::allocator_traits<Allocator>::is_always_equal::value) &&
3876 ((std::is_nothrow_move_constructible_v<value_type> &&
3877 std::is_nothrow_move_assignable_v<value_type> &&
3878 std::is_nothrow_swappable_v<value_type>) ||
3879 InlineCapacity == 0))
3880 requires(MoveInsertable && MoveAssignable && Swappable) ||
3881 ((std::is_same_v<std::allocator<value_type>, Allocator> ||
3882 std::allocator_traits<
3883 Allocator>::propagate_on_container_swap::value ||
3884 std::allocator_traits<Allocator>::is_always_equal::value) &&
3885 InlineCapacity == 0)
3927 if (
size() <= pos) {
3928 base::throw_index_error();
3934 if (
size() <= pos) {
3935 base::throw_index_error();
3961 return static_cast<size_type>(base::get_size());
3970 return static_cast<size_type>(base::get_max_size());
3974 return static_cast<size_type>(base::get_capacity());
3978 return base::copy_allocator();
3982 requires CopyInsertable && CopyAssignable
3984 return emplace(pos, value);
3988 requires MoveInsertable && MoveAssignable
3990 return emplace(pos, std::move(value));
3995 requires CopyInsertable && CopyAssignable
3997 return iterator(base::insert_copies(base::ptr_cast(pos), count, value));
4004 template <std::input_iterator InputIt>
4005 requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value &&
4006 MoveInsertable && MoveAssignable
4008 if (first == last) {
4009 return iterator(base::ptr_cast(pos));
4012 using iterator_cat =
4013 typename std::iterator_traits<InputIt>::iterator_category;
4015 base::insert_range(base::ptr_cast(pos), first, last, iterator_cat{}));
4019 std::initializer_list<value_type> ilist)
4020 requires EmplaceConstructible<const_reference>::value && MoveInsertable
4023 return insert(pos, ilist.begin(), ilist.end());
4026 template <
typename... Args>
4027 requires EmplaceConstructible<Args...>::value && MoveInsertable &&
4029 constexpr iterator emplace(const_iterator pos, Args&&... args) {
4031 base::emplace_at(base::ptr_cast(pos), std::forward<Args>(args)...));
4035 requires MoveAssignable && Erasable
4037 assert(0 <= (pos -
begin()) &&
4038 "`pos` is out of bounds (before `begin ()`).");
4039 assert(0 < (
end() - pos) &&
4040 "`pos` is out of bounds (at or after `end ()`).");
4042 return iterator(base::erase_at(base::ptr_cast(pos)));
4046 requires MoveAssignable && Erasable
4048 assert(0 <= (last - first) &&
"Invalid range.");
4049 assert(0 <= (first -
begin()) &&
4050 "`first` is out of bounds (before `begin ()`).");
4051 assert(0 <= (
end() - last) &&
"`last` is out of bounds (after `end ()`).");
4054 base::erase_range(base::ptr_cast(first), base::ptr_cast(last)));
4058 requires CopyInsertable
4060 emplace_back(value);
4064 requires MoveInsertable
4066 emplace_back(std::move(value));
4069 template <
typename... Args>
4070 requires EmplaceConstructible<Args...>::value && MoveInsertable
4072 return *base::append_element(std::forward<Args>(args)...);
4078 assert(!
empty() &&
"`pop_back ()` called on an empty `small_vector`.");
4083 requires MoveInsertable
4085 base::request_capacity(new_capacity);
4089 requires MoveInsertable
4091 base::shrink_to_size();
4101 requires MoveInsertable && DefaultInsertable
4103 base::resize_with(count);
4107 requires CopyInsertable
4109 base::resize_with(count, value);
4114 return !base::has_allocation();
4119 return base::is_inlinable();
4124 return static_cast<size_type>(inline_capacity_v);
4127 template <std::input_iterator InputIt>
4128 requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value &&
4132 using iterator_cat =
4133 typename std::iterator_traits<InputIt>::iterator_category;
4134 base::template append_range<policy>(first, last, iterator_cat{});
4138 constexpr small_vector& append(std::initializer_list<value_type> ilist)
4139 requires EmplaceConstructible<const_reference>::value && MoveInsertable
4141 return append(ilist.begin(), ilist.end());
4144 template <
unsigned I>
4145 constexpr small_vector& append(
const small_vector<T, I, Allocator>& other)
4146 requires CopyInsertable
4148 return append(other.begin(), other.end());
4151 template <
unsigned I>
4152 constexpr small_vector& append(small_vector<T, I, Allocator>&& other)
4153 requires MoveInsertable
4156 using move_iter_type =
typename std::conditional_t<
4157 base::template relocate_with_move_v<value_type>,
4158 std::move_iterator<iterator>, iterator>;
4160 append(move_iter_type{other.begin()}, move_iter_type{other.end()});
4166template <
typename T,
unsigned InlineCapacityLHS,
unsigned InlineCapacityRHS,
4175template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4183template <
typename T,
unsigned InlineCapacityLHS,
unsigned InlineCapacityRHS,
4185 requires std::three_way_comparable<T>
4189 return std::lexicographical_compare_three_way(
4193template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4194 requires std::three_way_comparable<T>
4198 return std::lexicographical_compare_three_way(
4202template <
typename T,
unsigned InlineCapacityLHS,
unsigned InlineCapacityRHS,
4207 constexpr auto comparison = [](
const T& l,
const T& r) {
4208 return (l < r) ? std::weak_ordering::less
4209 : (r < l) ? std::weak_ordering::greater
4210 : std::weak_ordering::equivalent;
4213 return std::lexicographical_compare_three_way(
4217template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4221 constexpr auto comparison = [](
const T& l,
const T& r) {
4222 return (l < r) ? std::weak_ordering::less
4223 : (r < l) ? std::weak_ordering::greater
4224 : std::weak_ordering::equivalent;
4227 return std::lexicographical_compare_three_way(
4231template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4234 rhs)
noexcept(
noexcept(lhs.swap(rhs)))
4242template <
typename T,
unsigned InlineCapacity,
typename Allocator,
typename U>
4243inline constexpr typename small_vector<T, InlineCapacity, Allocator>::size_type
4245 const auto original_size = v.
size();
4247 return original_size - v.
size();
4250template <
typename T,
unsigned InlineCapacity,
typename Allocator,
4252inline constexpr typename small_vector<T, InlineCapacity, Allocator>::size_type
4254 const auto original_size = v.
size();
4256 return original_size - v.
size();
4259template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4265template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4266constexpr typename small_vector<T, InlineCapacity, Allocator>::const_iterator
4271template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4272constexpr typename small_vector<T, InlineCapacity, Allocator>::const_iterator
4277template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4283template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4284constexpr typename small_vector<T, InlineCapacity, Allocator>::const_iterator
4289template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4290constexpr typename small_vector<T, InlineCapacity, Allocator>::const_iterator
4295template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4296constexpr typename small_vector<T, InlineCapacity, Allocator>::reverse_iterator
4301template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4303 typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
4308template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4310 typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
4315template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4316constexpr typename small_vector<T, InlineCapacity, Allocator>::reverse_iterator
4321template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4323 typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
4328template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4330 typename small_vector<T, InlineCapacity, Allocator>::const_reverse_iterator
4335template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4341template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4342constexpr typename std::common_type_t<
4343 std::ptrdiff_t,
typename std::make_signed_t<
typename small_vector<
4344 T, InlineCapacity, Allocator>::size_type>>
4346 using ret_type =
typename std::common_type_t<
4347 std::ptrdiff_t,
typename std::make_signed_t<
decltype(v.size())>>;
4348 return static_cast<ret_type
>(v.size());
4351template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4358template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4364template <
typename T,
unsigned InlineCapacity,
typename Allocator>
4365constexpr typename small_vector<T, InlineCapacity, Allocator>::const_pointer
4372 unsigned InlineCapacity = default_buffer_size_v<
4373 std::allocator<typename std::iterator_traits<InputIt>::value_type>>,
4374 typename Allocator =
4375 std::allocator<typename std::iterator_traits<InputIt>::value_type>>
4378 InlineCapacity, Allocator>;
Definition small_vector.hpp:499
constexpr reference operator*() const noexcept
Definition small_vector.hpp:566
constexpr small_vector_iterator & operator-=(difference_type n) noexcept
Definition small_vector.hpp:557
typename std::iterator_traits< Pointer >::pointer pointer
Definition small_vector.hpp:503
typename std::iterator_traits< Pointer >::value_type value_type
Definition small_vector.hpp:502
constexpr small_vector_iterator(const small_vector_iterator< U, D > &other) noexcept
Definition small_vector.hpp:526
constexpr small_vector_iterator operator--(int) noexcept
Definition small_vector.hpp:544
constexpr small_vector_iterator operator+(difference_type n) const noexcept
Definition small_vector.hpp:553
DifferenceType difference_type
Definition small_vector.hpp:501
constexpr small_vector_iterator & operator+=(difference_type n) noexcept
Definition small_vector.hpp:548
constexpr small_vector_iterator & operator++() noexcept
Definition small_vector.hpp:530
std::contiguous_iterator_tag iterator_concept
Definition small_vector.hpp:507
constexpr small_vector_iterator operator++(int) noexcept
Definition small_vector.hpp:535
typename std::iterator_traits< Pointer >::iterator_category iterator_category
Definition small_vector.hpp:506
typename std::iterator_traits< Pointer >::reference reference
Definition small_vector.hpp:504
small_vector_iterator(const small_vector_iterator &)=default
small_vector_iterator(small_vector_iterator &&) noexcept=default
constexpr small_vector_iterator() noexcept
Definition small_vector.hpp:518
constexpr small_vector_iterator(const Pointer &p) noexcept
Definition small_vector.hpp:521
constexpr const Pointer & base() const noexcept
Definition small_vector.hpp:576
constexpr small_vector_iterator & operator--() noexcept
Definition small_vector.hpp:539
constexpr reference operator[](difference_type n) const noexcept
Definition small_vector.hpp:572
constexpr pointer operator->() const noexcept
Definition small_vector.hpp:570
constexpr small_vector_iterator operator-(difference_type n) const noexcept
Definition small_vector.hpp:562
Definition small_vector.hpp:3616
::value &&std::forward_iterator< InputIt > MoveInsertable constexpr small_vector(InputIt first, InputIt last, const allocator_type &alloc=allocator_type())
Definition small_vector.hpp:3736
constexpr const_reverse_iterator crbegin() const noexcept
Definition small_vector.hpp:3914
constexpr small_vector(small_vector< T, I, Allocator > &&other, const allocator_type &alloc)
Definition small_vector.hpp:3769
constexpr const_iterator end() const noexcept
Definition small_vector.hpp:3900
constexpr const_reference operator[](size_type pos) const
Definition small_vector.hpp:3944
constexpr small_vector() noexcept(noexcept(allocator_type()))=default
constexpr iterator erase(const_iterator first, const_iterator last) &&Erasable
Definition small_vector.hpp:4045
constexpr size_type capacity() const noexcept
Definition small_vector.hpp:3973
typename base::size_type size_type
Definition small_vector.hpp:3630
constexpr const_reference at(size_type pos) const
Definition small_vector.hpp:3933
::value constexpr small_vector(size_type count, Generator g, const allocator_type &alloc=allocator_type())
Definition small_vector.hpp:3729
::value &&MoveInsertable &&MoveAssignable constexpr iterator insert(const_iterator pos, InputIt first, InputIt last)
Definition small_vector.hpp:4007
constexpr void swap(small_vector &other) noexcept((std::is_same_v< std::allocator< value_type >, Allocator >||std::allocator_traits< Allocator >::propagate_on_container_swap::value||std::allocator_traits< Allocator >::is_always_equal::value) &&((std::is_nothrow_move_constructible_v< value_type > &&std::is_nothrow_move_assignable_v< value_type > &&std::is_nothrow_swappable_v< value_type >)||InlineCapacity==0))
Definition small_vector.hpp:3872
constexpr const_reverse_iterator crend() const noexcept
Definition small_vector.hpp:3924
constexpr void pop_back()
Definition small_vector.hpp:4075
constexpr iterator insert(const_iterator pos, const_reference value) &&CopyAssignable
Definition small_vector.hpp:3981
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition small_vector.hpp:3636
constexpr small_vector & operator=(small_vector &&other) noexcept((std::is_same_v< std::allocator< value_type >, Allocator >||std::allocator_traits< Allocator >::propagate_on_container_move_assignment::value||std::allocator_traits< Allocator >::is_always_equal::value) &&((std::is_nothrow_move_assignable_v< value_type > &&std::is_nothrow_move_constructible_v< value_type >)||InlineCapacity==0)) &&MoveAssignable
Definition small_vector.hpp:3784
constexpr small_vector(small_vector &&other, const allocator_type &alloc)
Definition small_vector.hpp:3712
constexpr void resize(size_type count, const_reference value)
Definition small_vector.hpp:4106
constexpr iterator insert(const_iterator pos, std::initializer_list< value_type > ilist)
Definition small_vector.hpp:4018
constexpr small_vector(small_vector &&other) noexcept(std::is_nothrow_move_constructible_v< value_type >||InlineCapacity==0)
Definition small_vector.hpp:3700
constexpr ~small_vector()=default
constexpr const_iterator cend() const noexcept
Definition small_vector.hpp:3904
&&MoveAssignable constexpr void assign(small_vector< T, I, Allocator > &&other) noexcept(I<=InlineCapacity &&(std::is_same_v< std::allocator< value_type >, Allocator >||std::allocator_traits< Allocator >::propagate_on_container_move_assignment::value||std::allocator_traits< Allocator >::is_always_equal::value) &&std::is_nothrow_move_assignable_v< value_type > &&std::is_nothrow_move_constructible_v< value_type >)
Definition small_vector.hpp:3861
::value &&MoveInsertable constexpr small_vector & append(InputIt first, InputIt last)
Definition small_vector.hpp:4130
constexpr size_type size() const noexcept
Definition small_vector.hpp:3960
constexpr void clear() noexcept
Definition small_vector.hpp:4094
constexpr small_vector(small_vector< T, I, Allocator > &&other) noexcept(std::is_nothrow_move_constructible< value_type >::value &&I< InlineCapacity)
Definition small_vector.hpp:3754
constexpr const_reference back() const
Definition small_vector.hpp:3954
constexpr iterator insert(const_iterator pos, size_type count, const_reference value) &&CopyAssignable
Definition small_vector.hpp:3993
constexpr void assign(small_vector &&other) noexcept((std::is_same_v< std::allocator< value_type >, Allocator >||std::allocator_traits< Allocator >::propagate_on_container_move_assignment::value||std::allocator_traits< Allocator >::is_always_equal::value) &&((std::is_nothrow_move_assignable_v< value_type > &&std::is_nothrow_move_constructible_v< value_type >)||InlineCapacity==0)) &&MoveAssignable
Definition small_vector.hpp:3844
Allocator allocator_type
Definition small_vector.hpp:3629
constexpr void assign(std::initializer_list< value_type > ilist)
Definition small_vector.hpp:3824
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition small_vector.hpp:3641
constexpr void reserve(size_type new_capacity)
Definition small_vector.hpp:4082
constexpr reference at(size_type pos)
Definition small_vector.hpp:3926
constexpr bool empty() const noexcept
Definition small_vector.hpp:3965
constexpr reverse_iterator rbegin() noexcept
Definition small_vector.hpp:3906
constexpr small_vector(const small_vector< T, I, Allocator > &other)
Definition small_vector.hpp:3749
value_type & reference
Definition small_vector.hpp:3632
constexpr bool inlined() const noexcept
Definition small_vector.hpp:4113
constexpr pointer data() noexcept
Definition small_vector.hpp:3956
constexpr small_vector(size_type count, const_reference value, const allocator_type &alloc=allocator_type())
Definition small_vector.hpp:3721
constexpr void push_back(value_type &&value)
Definition small_vector.hpp:4063
constexpr const_reverse_iterator rend() const noexcept
Definition small_vector.hpp:3920
::value &&MoveInsertable constexpr reference emplace_back(Args &&... args)
Definition small_vector.hpp:4071
constexpr const_reference front() const
Definition small_vector.hpp:3950
constexpr reference operator[](size_type pos)
Definition small_vector.hpp:3940
constexpr void resize(size_type count) &&DefaultInsertable
Definition small_vector.hpp:4100
constexpr allocator_type get_allocator() const noexcept
Definition small_vector.hpp:3977
constexpr const_pointer data() const noexcept
Definition small_vector.hpp:3958
constexpr reverse_iterator rend() noexcept
Definition small_vector.hpp:3916
constexpr size_type max_size() const noexcept
Definition small_vector.hpp:3969
typename std::allocator_traits< allocator_type >::pointer pointer
Definition small_vector.hpp:3634
constexpr void assign(size_type count, const_reference value) &&CopyAssignable
Definition small_vector.hpp:3809
constexpr void shrink_to_fit()
Definition small_vector.hpp:4088
constexpr small_vector & operator=(std::initializer_list< value_type > ilist) &&CopyAssignable
Definition small_vector.hpp:3802
::value &&std::forward_iterator< InputIt > MoveInsertable constexpr void assign(InputIt first, InputIt last)
Definition small_vector.hpp:3818
constexpr iterator insert(const_iterator pos, value_type &&value) &&MoveAssignable
Definition small_vector.hpp:3987
constexpr small_vector(size_type count, const allocator_type &alloc=allocator_type())
Definition small_vector.hpp:3716
constexpr small_vector(const small_vector< T, I, Allocator > &other, const allocator_type &alloc)
Definition small_vector.hpp:3763
constexpr bool inlinable() const noexcept
Definition small_vector.hpp:4118
T value_type
Definition small_vector.hpp:3628
constexpr small_vector(const allocator_type &alloc) noexcept
Definition small_vector.hpp:3705
constexpr reference front()
Definition small_vector.hpp:3948
const value_type & const_reference
Definition small_vector.hpp:3633
typename base::difference_type difference_type
Definition small_vector.hpp:3631
std::reverse_iterator< iterator > reverse_iterator
Definition small_vector.hpp:3640
constexpr small_vector(const small_vector &other, const allocator_type &alloc)
Definition small_vector.hpp:3708
constexpr small_vector(std::initializer_list< value_type > init, const allocator_type &alloc=allocator_type())
Definition small_vector.hpp:3742
constexpr const_iterator cbegin() const noexcept
Definition small_vector.hpp:3896
constexpr iterator end() noexcept
Definition small_vector.hpp:3898
constexpr void push_back(const_reference value)
Definition small_vector.hpp:4057
constexpr iterator begin() noexcept
Definition small_vector.hpp:3890
constexpr const_iterator begin() const noexcept
Definition small_vector.hpp:3892
static consteval size_type inline_capacity() noexcept
Definition small_vector.hpp:4123
constexpr const_reverse_iterator rbegin() const noexcept
Definition small_vector.hpp:3910
constexpr iterator erase(const_iterator pos) &&Erasable
Definition small_vector.hpp:4034
constexpr reference back()
Definition small_vector.hpp:3952
Definition small_vector.hpp:209
Definition small_vector.hpp:382
Definition small_vector.hpp:187
Definition small_vector.hpp:37
Definition small_vector.hpp:54
Definition small_vector.hpp:184
Definition small_vector.hpp:60
Definition small_vector.hpp:83
Definition small_vector.hpp:95
Definition small_vector.hpp:165
Definition small_vector.hpp:75
Definition small_vector.hpp:153
Definition small_vector.hpp:42
Definition small_vector.hpp:124
Definition small_vector.hpp:111
Definition small_vector.hpp:174
Definition small_vector.hpp:80
Definition small_vector.hpp:88
Definition small_vector.hpp:159
Definition small_vector.hpp:57
Definition small_vector.hpp:67
Definition small_vector.hpp:101
Definition small_vector.hpp:48
Definition small_vector.hpp:91
Definition small_vector.hpp:191
Definition small_vector.hpp:108
Definition small_vector.hpp:45
Definition small_vector.hpp:432
Definition small_vector.hpp:436
Definition small_vector.hpp:397
Definition small_vector.hpp:404
Definition small_vector.hpp:419
Definition small_vector.hpp:411
Definition small_vector.hpp:391
Definition small_vector.hpp:427
Definition small_vector.hpp:423
Definition small_vector.hpp:394
Definition small_vector.hpp:400
Definition small_vector.hpp:415
Definition small_vector.hpp:408
Definition Expression.hpp:18
IntrusiveSharedPtr< T > AllocateIntrusiveShared(Alloc alloc, Args &&... args)
Definition IntrusiveSharedPtr.hpp:275
constexpr small_vector< T, InlineCapacity, Allocator >::pointer data(small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4359
small_vector(InputIt, InputIt, Allocator=Allocator()) -> small_vector< typename std::iterator_traits< InputIt >::value_type, InlineCapacity, Allocator >
constexpr bool empty(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4353
constexpr small_vector_iterator< Pointer, DifferenceType > operator+(DifferenceType n, const small_vector_iterator< Pointer, DifferenceType > &it) noexcept
Definition small_vector.hpp:692
constexpr small_vector< T, InlineCapacity, Allocator >::iterator begin(small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4260
constexpr auto operator<=>(const small_vector_iterator< PointerLHS, DifferenceTypeLHS > &lhs, const small_vector_iterator< PointerRHS, DifferenceTypeRHS > &rhs) noexcept(noexcept(lhs.base()<=> rhs.base()))
Definition small_vector.hpp:636
constexpr small_vector< T, InlineCapacity, Allocator >::reverse_iterator rend(small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4317
constexpr std::common_type_t< std::ptrdiff_t, typename std::make_signed_t< typename small_vector< T, InlineCapacity, Allocator >::size_type > > ssize(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4345
EqualityConstraints operator==(LHS &&lhs, RHS &&rhs)
Definition Variable.hpp:681
constexpr small_vector< T, InlineCapacity, Allocator >::size_type erase_if(small_vector< T, InlineCapacity, Allocator > &v, Pred pred)
Definition small_vector.hpp:4253
constexpr small_vector< T, InlineCapacity, Allocator >::const_reverse_iterator crbegin(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4311
constexpr void swap(function_ref< R(Args...)> &lhs, function_ref< R(Args...)> &rhs) noexcept
Definition FunctionRef.hpp:92
constexpr DifferenceType operator-(const small_vector_iterator< PointerLHS, DifferenceType > &lhs, const small_vector_iterator< PointerRHS, DifferenceType > &rhs) noexcept
Definition small_vector.hpp:678
constexpr small_vector< T, InlineCapacity, Allocator >::reverse_iterator rbegin(small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4297
constexpr small_vector< T, InlineCapacity, Allocator >::iterator end(small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4278
constexpr small_vector< T, InlineCapacity, Allocator >::const_reverse_iterator crend(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4331
constexpr small_vector< T, InlineCapacity, Allocator >::size_type erase(small_vector< T, InlineCapacity, Allocator > &v, const U &value)
Definition small_vector.hpp:4244
constexpr small_vector< T, InlineCapacity, Allocator >::const_iterator cbegin(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4273
constexpr small_vector< T, InlineCapacity, Allocator >::const_iterator cend(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4291
constexpr small_vector< T, InlineCapacity, Allocator >::size_type size(const small_vector< T, InlineCapacity, Allocator > &v) noexcept
Definition small_vector.hpp:4336
constexpr unsigned default_buffer_size_v
Definition small_vector.hpp:495
Definition small_vector.hpp:455
Allocator allocator_type
Definition small_vector.hpp:468
typename std::allocator_traits< allocator_type >::value_type value_type
Definition small_vector.hpp:469
Definition small_vector.hpp:1117
Definition small_vector.hpp:1101
Definition small_vector.hpp:1133
Definition small_vector.hpp:2289
Definition small_vector.hpp:2569