[libcxx-commits] [libcxx] [libcxx] adds a size-based representation for `vector`'s unstable ABI (PR #155330)
Christopher Di Bella via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 14 18:25:37 PST 2026
https://github.com/cjdb updated https://github.com/llvm/llvm-project/pull/155330
>From ba94eeba1e22ebee9708c770c3b7da73eaad131e Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Mon, 25 Aug 2025 23:06:45 +0000
Subject: [PATCH 1/8] [libcxx] adds a size-based representation for `vector`'s
unstable ABI
**tl;dr** We can significantly improve the runtime performance of
`std::vector` by changing its representation from three pointers to one
pointer and two integers. This document explains the details of this
change, along with the justifications for making it. See the [RFC] for
more information.
This commit changes `std::vector`'s representation in a similar manner
to `__split_buffer` in #139632. We introduce a layout type that tracks
implementation details that differ between the pointer-based vector
and size-based vector representations. `vector` does not parameterise
its layout type, unlike `__split_buffer`. `__split_buffer` is used by
both `vector` and `deque`, and being able to take an ABI break on
`vector` doesn't automatically mean that users can also tolerate a break
on `deque`. The most convenient way to work around this problem is to
parameterise the layout type. Users of `std::vector` should not depend
on its layout, and libc++ has no internal reason to toggle it, so we
keep the representation concrete.
To use this feature, you'll need to configure libc++ so that it's built
with `-DLIBCXX_UNSTABLE_ABI=Yes`.
[RFC]: https://discourse.llvm.org/t/adding-a-size-based-vector-to-libc-s-unstable-abi/86306
---
libcxx/include/__configuration/abi.h | 1 +
libcxx/include/__split_buffer | 8 +-
libcxx/include/__vector/vector.h | 800 ++++++++++++------
.../alg.swap/ranges.swap_ranges.pass.cpp | 54 +-
libcxx/utils/gdb/libcxx/printers.py | 18 +-
5 files changed, 597 insertions(+), 284 deletions(-)
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 38b85c6ac70de..70aef42b487ac 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -79,6 +79,7 @@
# define _LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
+# define _LIBCPP_ABI_SIZE_BASED_VECTOR
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1e05e4df8ba0f..9a55f855bbfda 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -268,7 +268,6 @@ public:
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
// Size-based __split_buffers track their size directly: we need to explicitly update the size
// when the front is adjusted.
- __size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
__set_sentinel(__new_end);
}
@@ -277,7 +276,6 @@ public:
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
// Size-based __split_buffers track their size directly: we need to explicitly update the size
// when the front is adjusted.
- __size_ -= __new_begin - __begin_;
__begin_ = __new_begin;
__set_sentinel(__new_size);
}
@@ -316,9 +314,9 @@ public:
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
- __split_buffer_pointer_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_pointer_layout>,
- value_type,
- __alloc_rr&>& __other) _NOEXCEPT {
+ __split_buffer_size_layout<__split_buffer<value_type, __alloc_rr&, __split_buffer_size_layout>,
+ value_type,
+ __alloc_rr&>& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 7051e044314ea..9e94fe75123eb 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -55,6 +55,7 @@
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_pointer.h>
#include <__type_traits/is_same.h>
+#include <__type_traits/is_swappable.h>
#include <__type_traits/is_trivially_relocatable.h>
#include <__type_traits/type_identity.h>
#include <__utility/declval.h>
@@ -82,25 +83,334 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template <class _Vector, class _Tp, class _Allocator>
+class __vector_layout {
+public:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
+ using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator&, __split_buffer_size_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+
+ _LIBCPP_HIDE_FROM_ABI __vector_layout() = default;
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
+ _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __alloc_(__a) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __alloc_(std::move(__a)) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_)),
+ __size_(std::move(__other.__size_)),
+ __cap_(std::move(__other.__cap_)),
+ __alloc_(std::move(__other.__alloc_)) {
+ __other.__begin_ = nullptr;
+ __other.__size_ = 0;
+ __other.__cap_ = 0;
+ }
+
+ // Capacity
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return __size_;
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __size_ == 0;
+ }
+
+ // Access
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
+ return __alloc_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
+ __allocator_ref() const _NOEXCEPT {
+ return __alloc_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __x.__begin_);
+ std::swap(__size_, __x.__size_);
+ std::swap(__cap_, __x.__cap_);
+ std::__swap_allocator(__alloc_, __x.__alloc_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
+ return __begin_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ return __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __size_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __end - __begin_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __size_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ __cap_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ || __cap_)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+
+private:
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
+};
+#else
+template <class _Vector, class _Tp, class _Allocator>
+class __vector_layout {
+public:
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
+ using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator&, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
+
+ // Can't be defaulted due to _LIBCPP_COMPRESSED_PAIR not being an aggregate in C++03 and C++11.
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
+ _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
+ : __cap_(nullptr) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
+ _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
+ : __cap_(nullptr), __alloc_(__a) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __cap_(nullptr), __alloc_(std::move(__a)) {}
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
+ _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
+ : __begin_(std::move(__other.__begin_)),
+ __end_(std::move(__other.__end_)),
+ __cap_(std::move(__other.__cap_)),
+ __alloc_(std::move(__other.__alloc_)) {
+ __other.__begin_ = nullptr;
+ __other.__end_ = nullptr;
+ __other.__cap_ = nullptr;
+ }
+
+ // Capacity
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __begin_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __begin_ == __end_;
+ }
+
+ // Access
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
+ return __alloc_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
+ __allocator_ref() const _NOEXCEPT {
+ return __alloc_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __x.__begin_);
+ std::swap(__end_, __x.__end_);
+ std::swap(__cap_, __x.__cap_);
+ std::__swap_allocator(__alloc_, __x.__alloc_);
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
+ return __begin_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __end_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __begin_ + __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
+ __end_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+
+private:
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
+};
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector {
- template <class _Up, class _Alloc>
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Up, _Alloc, __split_buffer_pointer_layout>;
+class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
+ using __base _LIBCPP_NODEBUG = __vector_layout<vector, _Tp, _Allocator>;
+ using __self _LIBCPP_NODEBUG = vector;
+ using __base::__allocator_ref;
+ using __base::__end_pointer;
+ using __base::__is_full;
+ using __base::__raw_begin;
+ using __base::__raw_capacity;
+ using __base::__raw_sentinel;
+ using __base::__remaining_capacity;
+ using __base::__set_capacity;
+ using __base::__set_sentinel;
+ using __base::__set_valid_range;
+ using typename __base::__alloc_traits;
+ using typename __base::__sentinel_type;
+ using typename __base::__split_buffer;
public:
- //
- // Types
- //
- using __self _LIBCPP_NODEBUG = vector;
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using reference = typename __base::reference;
+ using const_reference = typename __base::const_reference;
+ using size_type = typename __base::size_type;
+ using difference_type = typename __base::difference_type;
+ using pointer = typename __base::pointer;
+ using const_pointer = typename __base::const_pointer;
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
// Users might provide custom allocators, and prior to C++20 we have no existing way to detect whether the allocator's
// pointer type is contiguous (though it has to be by the Standard). Using the wrapper type ensures the iterator is
@@ -114,6 +424,8 @@ class vector {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using __base::__invariants;
+
// A vector containers the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
// - allocator_type: may be trivially relocatable, so it's checked
@@ -138,7 +450,7 @@ class vector {
#else
noexcept
#endif
- : __alloc_(__a) {
+ : __base(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -152,7 +464,7 @@ class vector {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -174,7 +486,7 @@ class vector {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -197,7 +509,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
__init_with_sentinel(__first, __last);
}
@@ -218,7 +530,7 @@ class vector {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -227,7 +539,7 @@ class vector {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __alloc_(__alloc) {
+ : __base(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -244,10 +556,10 @@ class vector {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__begin_ != nullptr) {
+ if (__vec_.__raw_begin() != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__allocator_ref(), __vec_.__raw_begin(), __vec_.capacity());
}
}
@@ -259,13 +571,13 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) {
- __init_with_size(__x.__begin_, __x.__end_, __x.size());
+ : __base(__alloc_traits::select_on_container_copy_construction(__x.__allocator_ref())) {
+ __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- __init_with_size(__x.__begin_, __x.__end_, __x.size());
+ : __base(__a) {
+ __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -276,7 +588,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __alloc_(__a) {
+ : __base(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -339,23 +651,23 @@ class vector {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return this->__alloc_;
+ return __allocator_ref();
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(__raw_begin()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__begin_));
+ return __make_iter(__add_alignment_assumption(__raw_begin()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__end_));
+ return __make_iter(__add_alignment_assumption(__end_pointer()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(this->__end_));
+ return __make_iter(__add_alignment_assumption(__end_pointer()));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() _NOEXCEPT {
@@ -389,17 +701,19 @@ class vector {
//
// [vector.capacity], capacity
//
+
+ // Capacity
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(this->__end_ - this->__begin_);
+ return __base::size();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(this->__cap_ - this->__begin_);
+ return __base::capacity();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return this->__begin_ == this->__end_;
+ return __base::empty();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__allocator_ref()), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -409,50 +723,48 @@ class vector {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return this->__begin_[__n];
+ return __raw_begin()[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *__raw_begin();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *this->__begin_;
+ return *__raw_begin();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base::back();
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(this->__end_ - 1);
+ return __base::back();
}
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(__raw_begin());
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(this->__begin_);
+ return std::__to_address(__raw_begin());
}
//
@@ -477,7 +789,7 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -490,7 +802,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
- this->__destruct_at_end(this->__end_ - 1);
+ this->__destruct_at_end(__end_pointer() - 1);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const_reference __x);
@@ -546,41 +858,39 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(this->__begin_);
+ __base_destruct_at_end(__raw_begin());
__annotate_shrink(__old_size);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector& __other)
#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT;
+ _NOEXCEPT
#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
#endif
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+ {
+ __base::swap(__other);
+ }
private:
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
-
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
- // Precondition: __begin_ == __end_ == __cap_ == nullptr
+ // Precondition: begin() == nullptr
+ // Precondition: size() == 0
+ // Precondition: capacity() == 0
// Precondition: __n > 0
// Postcondition: capacity() >= __n
// Postcondition: size() == 0
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(this->__alloc_, __n);
- __begin_ = __allocation.ptr;
- __end_ = __allocation.ptr;
- __cap_ = __begin_ + __allocation.count;
+ auto __allocation = std::__allocate_at_least(__allocator_ref(), __n);
+ __set_valid_range(__allocation.ptr, static_cast<size_type>(0));
+ __set_capacity(__allocation.count);
__annotate_new(0);
}
@@ -628,7 +938,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, *__first);
+ __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), *__first);
*__position = std::move(__tmp.get());
}
}
@@ -672,8 +982,8 @@ class vector {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(this->__begin_),
- std::__wrap_iter<pointer>(this->__cap_));
+ std::__wrap_iter<pointer>(__raw_begin()),
+ std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
@@ -684,17 +994,16 @@ class vector {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(this->__begin_),
- std::__wrap_iter<const_pointer>(this->__cap_));
+ std::__wrap_iter<const_pointer>(__raw_begin()),
+ std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
- __swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p);
+ __swap_out_circular_buffer(__split_buffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__move_range(pointer __from_s, pointer __from_e, pointer __to);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, true_type)
@@ -708,7 +1017,7 @@ class vector {
}
template <class... _Args>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline pointer __emplace_back_slow_path(_Args&&... __args);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __emplace_back_slow_path(_Args&&... __args);
// The following functions are no-ops outside of AddressSanitizer mode.
// We call annotations for every allocator, unless explicitly disabled.
@@ -741,14 +1050,14 @@ class vector {
struct _ConstructTransaction {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
- : __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) {
+ : __v_(__v), __pos_(__v.__end_pointer()), __new_end_(__pos_ + __n) {
__v_.__annotate_increase(__n);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
- __v_.__end_ = __pos_;
+ __v_.__set_sentinel(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__begin_);
+ __v_.__annotate_shrink(__new_end_ - __v_.__raw_begin());
}
}
@@ -761,10 +1070,10 @@ class vector {
};
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
- pointer __soon_to_be_end = this->__end_;
+ pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end));
- this->__end_ = __new_last;
+ __alloc_traits::destroy(__allocator_ref(), std::__to_address(--__soon_to_be_end));
+ __set_sentinel(__new_last);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c) {
@@ -782,20 +1091,21 @@ class vector {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (__allocator_ref() != __c.__allocator_ref()) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
- this->__begin_ = this->__end_ = this->__cap_ = nullptr;
+ __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __set_valid_range(nullptr, static_cast<size_type>(0));
+ __set_capacity(static_cast<__sentinel_type>(0));
}
- this->__alloc_ = __c.__alloc_;
+ __allocator_ref() = __c.__allocator_ref();
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- this->__alloc_ = std::move(__c.__alloc_);
+ __allocator_ref() = std::move(__c.__allocator_ref());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -815,19 +1125,17 @@ class vector {
return __p;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer<_Tp, allocator_type&>& __sb) {
- auto __vector_begin = __begin_;
- auto __vector_sentinel = __end_;
- auto __vector_cap = __cap_;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer& __sb) {
+ auto __vector_begin = __raw_begin();
+ auto __vector_sentinel = __raw_sentinel();
+ auto __vector_cap = __raw_capacity();
auto __sb_begin = __sb.begin();
auto __sb_sentinel = __sb.__raw_sentinel();
auto __sb_cap = __sb.__raw_capacity();
- // TODO: replace with __set_valid_range and __set_capacity when vector supports it.
- __begin_ = __sb_begin;
- __end_ = __sb_sentinel;
- __cap_ = __sb_cap;
+ __set_valid_range(__sb_begin, __sb_sentinel);
+ __set_capacity(__sb_cap);
__sb.__set_valid_range(__vector_begin, __vector_sentinel);
__sb.__set_capacity(__vector_cap);
@@ -855,47 +1163,53 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__begin_, __end_) into the front of __v and swaps the buffers of
-// *this and __v. It is assumed that __v provides space for exactly (__end_ - __begin_) objects in the front. This
+// __swap_out_circular_buffer relocates the objects in [__raw_begin(), size()) into the front of __v and swaps the
+// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) {
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_), std::__to_address(__new_begin));
+ __allocator_ref(),
+ std::__to_address(__raw_begin()),
+ std::__to_address(__end_pointer()),
+ std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
- __end_ = __begin_; // All the objects have been destroyed by relocating them.
+ __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+ // __v.__size_ += __size_;
__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
-// [__p, __end_) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __begin_) objects in the front and space for at least (__end_ - __p) objects in the back. This
-// function has a strong exception guarantee if __begin_ == __p || __end_ == __p.
+// __swap_out_circular_buffer relocates the objects in [__raw_begin(), __p) into the front of __v, the objects in
+// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
+// exactly (__p - __raw_begin()) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __raw_begin() == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
-vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
+vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) {
__annotate_delete();
pointer __ret = __v.begin();
- // Relocate [__p, __end_) first to avoid having a hole in [__begin_, __end_)
- // in case something in [__begin_, __p) throws.
+ pointer __end = __end_pointer();
+ // Relocate [__p, __end) first to avoid having a hole in [__raw_begin(), __end)
+ // in case something in [__raw_begin(), __p) throws.
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.end()));
- auto __relocated_so_far = __end_ - __p;
+ __allocator_ref(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
- __end_ = __p; // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __begin_);
+ __set_sentinel(
+ __raw_sentinel() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
+ auto __new_begin = __v.begin() - (__p - __raw_begin());
std::__uninitialized_allocator_relocate(
- this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
- __v.__set_valid_range(__new_begin, __v.end());
- __end_ = __begin_; // All the objects have been destroyed by relocating them.
+ __allocator_ref(), std::__to_address(__raw_begin()), std::__to_address(__p), std::__to_address(__new_begin));
+ __v.__set_valid_range(__new_begin, __v.size() + size());
+ __set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
+
__swap_layouts(__v);
__v.__set_data(__v.begin());
__annotate_new(size());
@@ -904,11 +1218,12 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (this->__begin_ != nullptr) {
+ if (__raw_begin() != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
- this->__begin_ = this->__end_ = this->__cap_ = nullptr;
+ __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __set_valid_range(nullptr, static_cast<size_type>(0));
+ __set_capacity(static_cast<size_type>(0));
}
}
@@ -925,7 +1240,7 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
return std::max<size_type>(2 * __cap, __new_size);
}
-// Default constructs __n objects starting at __end_
+// Default constructs __n objects starting at __end_pointer()
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -935,11 +1250,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(this->__alloc_, std::__to_address(__pos));
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos));
}
}
-// Copy constructs __n objects starting at __end_ from __x
+// Copy constructs __n objects starting at __end_pointer() from __x
// throws if construction throws
// Precondition: __n > 0
// Precondition: size() + __n <= capacity()
@@ -951,7 +1266,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), __x);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), __x);
}
}
@@ -960,7 +1275,8 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ =
+ std::__uninitialized_allocator_copy(__allocator_ref(), std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -970,22 +1286,22 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __alloc_(std::move(__x.__alloc_)) {
- this->__begin_ = __x.__begin_;
- this->__end_ = __x.__end_;
- this->__cap_ = __x.__cap_;
- __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr;
+ : __base(std::move(__x.__allocator_ref())) {
+ __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ __set_capacity(__x.__raw_capacity());
+ __x.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __x.__set_capacity(static_cast<size_type>(0));
}
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __alloc_(__a) {
- if (__a == __x.__alloc_) {
- this->__begin_ = __x.__begin_;
- this->__end_ = __x.__end_;
- this->__cap_ = __x.__cap_;
- __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr;
+ : __base(__a) {
+ if (__a == __x.__allocator_ref()) {
+ __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ __set_capacity(__x.__raw_capacity());
+ __x.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __x.__set_capacity(static_cast<size_type>(0));
} else {
typedef move_iterator<iterator> _Ip;
__init_with_size(_Ip(__x.begin()), _Ip(__x.end()), __x.size());
@@ -995,7 +1311,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (this->__alloc_ != __c.__alloc_) {
+ if (__allocator_ref() != __c.__allocator_ref()) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1007,10 +1323,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- this->__begin_ = __c.__begin_;
- this->__end_ = __c.__end_;
- this->__cap_ = __c.__cap_;
- __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr;
+ __set_valid_range(__c.__raw_begin(), __c.__raw_sentinel());
+ __set_capacity(__c.__raw_capacity());
+ __c.__set_valid_range(nullptr, static_cast<size_type>(0));
+ __c.__set_capacity(static_cast<size_type>(0));
}
template <class _Tp, class _Allocator>
@@ -1018,7 +1334,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__begin_, __x.__end_);
+ assign(__x.__raw_begin(), __x.__end_pointer());
}
return *this;
}
@@ -1027,10 +1343,11 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __begin_;
- for (; __first != __last && __cur != __end_; ++__first, (void)++__cur)
+ pointer __cur = __raw_begin();
+ pointer __end = __end_pointer();
+ for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
- if (__cur != __end_) {
+ if (__cur != __end) {
__destruct_at_end(__cur);
} else {
for (; __first != __last; ++__first)
@@ -1046,15 +1363,15 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
#if _LIBCPP_STD_VER >= 23
- auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
+ auto __mid = ranges::copy_n(std::move(__first), size(), __raw_begin()).in;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
#else
_Iterator __mid = std::next(__first, size());
- std::copy(__first, __mid, this->__begin_);
+ std::copy(__first, __mid, __raw_begin());
__construct_at_end(__mid, __last, __new_size - size());
#endif
} else {
- pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
+ pointer __m = std::__copy(std::move(__first), __last, __raw_begin()).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1068,11 +1385,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(this->__begin_, std::min(__n, __s), __u);
+ std::fill_n(__raw_begin(), std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(this->__begin_ + __n);
+ this->__destruct_at_end(__raw_begin() + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1085,7 +1402,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer<value_type, allocator_type&> __v(__n, size(), this->__alloc_);
+ __split_buffer __v(__n, size(), __allocator_ref());
__swap_out_circular_buffer(__v);
}
}
@@ -1096,7 +1413,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer<value_type, allocator_type&> __v(size(), size(), this->__alloc_);
+ __split_buffer __v(size(), size(), __allocator_ref());
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1111,15 +1428,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
template <class _Tp, class _Allocator>
template <class... _Args>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
+_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), size(), __allocator_ref());
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
- return this->__end_;
+ return __raw_sentinel();
}
// This makes the compiler inline `__else()` if `__cond` is known to be false. Currently LLVM doesn't do that without
@@ -1149,18 +1466,18 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
void
#endif
vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
- pointer __end = this->__end_;
+ auto __current_sentinel = __raw_sentinel();
std::__if_likely_else(
- __end < this->__cap_,
+ __current_sentinel < __raw_capacity(),
[&] {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
- ++__end;
+ ++__current_sentinel;
},
- [&] { __end = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
+ [&] { __current_sentinel = __emplace_back_slow_path(std::forward<_Args>(__args)...); });
- this->__end_ = __end;
+ __set_sentinel(__current_sentinel);
#if _LIBCPP_STD_VER >= 17
- return *(__end - 1);
+ return back();
#endif
}
@@ -1170,8 +1487,8 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = this->__begin_ + __ps;
- this->__destruct_at_end(std::move(__p + 1, this->__end_, __p));
+ pointer __p = __raw_begin() + __ps;
+ this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1179,9 +1496,9 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = this->__begin_ + (__first - begin());
+ pointer __p = __raw_begin() + (__first - begin());
if (__first != __last) {
- this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p));
+ this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
return __make_iter(__p);
}
@@ -1189,13 +1506,13 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
- pointer __old_last = this->__end_;
+ pointer __old_last = __end_pointer();
difference_type __n = __old_last - __to;
{
pointer __i = __from_s + __n;
_ConstructTransaction __tx(*this, __from_e - __i);
for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
- __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1204,19 +1521,20 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(__x);
} else {
- __move_range(__p, this->__end_, __p + 1);
+ __move_range(__p, __end, __p + 1);
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
- if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end_), std::addressof(__x)))
+ if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end), std::addressof(__x)))
++__xr;
*__p = *__xr;
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1226,16 +1544,17 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(std::move(__x));
} else {
- __move_range(__p, this->__end_, __p + 1);
+ __move_range(__p, __end, __p + 1);
*__p = std::move(__x);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1246,17 +1565,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = this->__begin_ + (__position - begin());
- if (this->__end_ < this->__cap_) {
- if (__p == this->__end_) {
+ pointer __p = __raw_begin() + (__position - begin());
+ if (!__is_full()) {
+ pointer __end = __end_pointer();
+ if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(this->__alloc_, std::forward<_Args>(__args)...);
- __move_range(__p, this->__end_, __p + 1);
+ __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), std::forward<_Args>(__args)...);
+ __move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1266,25 +1586,26 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = __raw_begin() + (__position - begin());
if (__n > 0) {
- if (__n <= static_cast<size_type>(this->__cap_ - this->__end_)) {
+ if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
- pointer __old_last = this->__end_;
- if (__n > static_cast<size_type>(this->__end_ - __p)) {
- size_type __cx = __n - (this->__end_ - __p);
+ pointer __end = __end_pointer();
+ pointer __old_last = __end;
+ if (__n > static_cast<size_type>(__end - __p)) {
+ size_type __cx = __n - (__end - __p);
__construct_at_end(__cx, __x);
__n -= __cx;
}
if (__n > 0) {
__move_range(__p, __old_last, __p + __old_n);
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
- if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end_), std::addressof(__x)))
+ if (std::__is_pointer_in_range(std::__to_address(__p), std::__to_address(__end), std::addressof(__x)))
__xr += __old_n;
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1297,27 +1618,35 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = this->__begin_ + __off;
- pointer __old_last = this->__end_;
- for (; this->__end_ != this->__cap_ && __first != __last; ++__first)
+ pointer __p = __raw_begin() + __off;
+ pointer __old_last = __end_pointer();
+ for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
if (__first == __last)
- (void)std::rotate(__p, __old_last, this->__end_);
+ (void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer<value_type, allocator_type&> __v(__alloc_);
- auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, this->__end_));
+ __split_buffer __v(__allocator_ref());
+ pointer __end = __end_pointer();
+ auto __guard = std::__make_exception_guard(
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__allocator_ref(), __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
- __split_buffer<value_type, allocator_type&> __merged(
- __recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
+ __split_buffer __merged(
+ __recommend(size() + __v.size()), __off, __allocator_ref()); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__old_last), std::__to_address(this->__end_), std::__to_address(__merged.end()));
- __guard.__complete(); // Release the guard once objects in [__old_last_, __end_) have been successfully relocated.
- __merged.__set_sentinel(__merged.end() + (this->__end_ - __old_last));
- this->__end_ = __old_last;
+ __allocator_ref(),
+ std::__to_address(__old_last),
+ std::__to_address(__end_pointer()),
+ std::__to_address(__merged.end()));
+ __guard.__complete(); // Release the guard once objects in [__old_last_, __end_pointer()) have been successfully
+ // relocated.
+ __merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
+ __set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
+ __allocator_ref(),
+ std::__to_address(__v.begin()),
+ std::__to_address(__v.end()),
+ std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1330,16 +1659,17 @@ template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = this->__begin_ + (__position - begin());
+ pointer __p = __raw_begin() + (__position - begin());
if (__n > 0) {
- if (__n <= this->__cap_ - this->__end_) {
- pointer __old_last = this->__end_;
- difference_type __dx = this->__end_ - __p;
+ if (__n <= static_cast<difference_type>(__remaining_capacity())) {
+ pointer __end = __end_pointer();
+ pointer __old_last = __end;
+ difference_type __dx = __end - __p;
if (__n > __dx) {
#if _LIBCPP_STD_VER >= 23
if constexpr (!forward_iterator<_Iterator>) {
__construct_at_end(std::move(__first), std::move(__last), __n);
- std::rotate(__p, __old_last, this->__end_);
+ std::rotate(__p, __old_last, __end);
} else
#endif
{
@@ -1355,7 +1685,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked(std::move(__first), __n, __p);
}
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1370,12 +1700,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(__raw_begin() + __new_size);
}
}
@@ -1386,55 +1716,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer<value_type, allocator_type&> __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(this->__begin_ + __new_size);
+ this->__destruct_at_end(__raw_begin() + __new_size);
}
}
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
-#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT
-#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
-#endif
-{
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || this->__alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(this->__begin_, __x.__begin_);
- std::swap(this->__end_, __x.__end_);
- std::swap(this->__cap_, __x.__cap_);
- std::__swap_allocator(this->__alloc_, __x.__alloc_);
-}
-
-template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
- if (this->__begin_ == nullptr) {
- if (this->__end_ != nullptr || this->__cap_ != nullptr)
- return false;
- } else {
- if (this->__begin_ > this->__end_)
- return false;
- if (this->__begin_ == this->__cap_)
- return false;
- if (this->__end_ > this->__cap_)
- return false;
- }
- return true;
-}
-
#if _LIBCPP_STD_VER >= 20
-template <>
-inline constexpr bool __format::__enable_insertable<vector<char>> = true;
+template <class _Allocator>
+inline constexpr bool __format::__enable_insertable<vector<char, _Allocator>> = true;
# if _LIBCPP_HAS_WIDE_CHARACTERS
-template <>
-inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
+template <class _Allocator>
+inline constexpr bool __format::__enable_insertable<vector<wchar_t, _Allocator>> = true;
# endif
#endif // _LIBCPP_STD_VER >= 20
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
index 85557ecbbfabc..da42ce56db30a 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/ranges.swap_ranges.pass.cpp
@@ -67,22 +67,6 @@ TEST_CONSTEXPR_CXX20 void test_iterators() {
}
}
-template <std::size_t N>
-constexpr void test_vector_bool() {
- { // Test swap_ranges() with aligned bytes
- std::vector<bool> f(N, false), t(N, true);
- std::ranges::swap_ranges(f, t);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
- }
- { // Test swap_ranges() with unaligned bytes
- std::vector<bool> f(N, false), t(N + 8, true);
- std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
- assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
- assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
- }
-}
-
constexpr bool test() {
{ // Validate swapping ranges directly
std::array r1 = {1, 2, 3};
@@ -183,15 +167,34 @@ constexpr bool test() {
});
});
- { // Test vector<bool>::iterator optimization
- test_vector_bool<8>();
- test_vector_bool<19>();
- test_vector_bool<32>();
- test_vector_bool<49>();
- test_vector_bool<64>();
- test_vector_bool<199>();
- test_vector_bool<256>();
+ return true;
+}
+
+// Test vector<bool>::iterator optimization
+template <std::size_t N>
+constexpr void test_vector_bool() {
+ { // Test swap_ranges() with aligned bytes
+ std::vector<bool> f(N, false), t(N, true);
+ std::ranges::swap_ranges(f, t);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin(), t.end(), [](bool b) { return !b; }));
}
+ { // Test swap_ranges() with unaligned bytes
+ std::vector<bool> f(N, false), t(N + 8, true);
+ std::ranges::swap_ranges(f.begin(), f.end(), t.begin() + 4, t.end() - 4);
+ assert(std::all_of(f.begin(), f.end(), [](bool b) { return b; }));
+ assert(std::all_of(t.begin() + 4, t.end() - 4, [](bool b) { return !b; }));
+ }
+}
+
+constexpr bool test_vector_bool() {
+ test_vector_bool<8>();
+ test_vector_bool<19>();
+ test_vector_bool<32>();
+ test_vector_bool<49>();
+ test_vector_bool<64>();
+ test_vector_bool<199>();
+ test_vector_bool<256>();
return true;
}
@@ -201,5 +204,8 @@ int main(int, char**) {
test();
static_assert(test());
+ test_vector_bool();
+ static_assert(test_vector_bool());
+
return 0;
}
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 1c8ef6d7feb97..1bfdd718e36bc 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -13,6 +13,7 @@
from __future__ import print_function
import re
+import sys
import gdb
import gdb.printing
@@ -351,17 +352,28 @@ def __init__(self, val):
"""Set val, length, capacity, and iterator for bool and normal vectors."""
self.val = val
self.typename = _remove_generics(_prettify_typename(val.type))
- begin = self.val["__begin_"]
if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
+ begin = self.val["__begin_"]
self.typename += "<bool>"
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- end = self.val["__end_"]
+ for i in val.type.fields():
+ if i.is_base_class:
+ base = val[i]
+ break
+
+ begin = base["__begin_"]
+ end = base["__end_"]
self.length = end - begin
- self.capacity = self.val["__cap_"] - begin
+ for i in base.type.fields():
+ if i.name == "__cap_":
+ self.capacity = base["__cap_"] - begin
+ elif i.name == None:
+ self.capacity = base[i]["__cap_"] - begin
+ break
self.iterator = self._VectorIterator(begin, end)
def to_string(self):
>From 0580dea4fe36bd54f2b6581411f4584087411c2b Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 21:14:12 +0000
Subject: [PATCH 2/8] works `__vector_layout` into `vector`
[jyknight pointed out that we'd probably end up with a smaller diff][1]
(and simpler code) if we remove the `__vector_layout` type. [This also
reduces the volume of debuginfo, as pointed out by rnk][2].
[1]: https://github.com/llvm/llvm-project/pull/155330#discussion_r2607411335
[2]: https://github.com/llvm/llvm-project/pull/155330#discussion_r2612499610
---
libcxx/include/__vector/vector.h | 712 ++++++++++++-------------------
1 file changed, 281 insertions(+), 431 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index a78ee5918517d..29cd205aeb8da 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -84,334 +84,18 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template <class _Vector, class _Tp, class _Allocator>
-class __vector_layout {
-public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = size_type;
-
- _LIBCPP_HIDE_FROM_ABI __vector_layout() = default;
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
- _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __alloc_(__a) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __alloc_(std::move(__a)) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __begin_(std::move(__other.__begin_)),
- __size_(std::move(__other.__size_)),
- __cap_(std::move(__other.__cap_)),
- __alloc_(std::move(__other.__alloc_)) {
- __other.__begin_ = nullptr;
- __other.__size_ = 0;
- __other.__cap_ = 0;
- }
-
- // Capacity
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __size_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __cap_;
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __size_ == 0;
- }
-
- // Access
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return __begin_[__size_ - 1];
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
- return __alloc_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
- __allocator_ref() const _NOEXCEPT {
- return __alloc_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __x.__begin_);
- std::swap(__size_, __x.__size_);
- std::swap(__cap_, __x.__cap_);
- std::__swap_allocator(__alloc_, __x.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
- return __begin_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
- return __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_capacity() const _NOEXCEPT {
- return __cap_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __begin_ + __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __size_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __size_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __end - __begin_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
- __size_ = __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
- __size_ = static_cast<size_type>(__pos - __begin_);
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
- __cap_ = static_cast<size_type>(__pos - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__size_ || __cap_)
- return false;
- } else {
- if (__size_ > __cap_)
- return false;
- }
- return true;
- }
-
-private:
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- [[no_unique_address]] allocator_type __alloc_;
-};
-#else
-template <class _Vector, class _Tp, class _Allocator>
-class __vector_layout {
-public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename __alloc_traits::size_type;
- using difference_type = typename __alloc_traits::difference_type;
- using pointer = typename __alloc_traits::pointer;
- using const_pointer = typename __alloc_traits::const_pointer;
- using __split_buffer _LIBCPP_NODEBUG = std::__split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = pointer;
-
- // Can't be defaulted due to _LIBCPP_COMPRESSED_PAIR not being an aggregate in C++03 and C++11.
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout()
- _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
- : __cap_(nullptr) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type const& __a)
- _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
- : __cap_(nullptr), __alloc_(__a) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __vector_layout(allocator_type&& __a)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __cap_(nullptr), __alloc_(std::move(__a)) {}
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __vector_layout(__vector_layout&& __other)
- _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
- : __begin_(std::move(__other.__begin_)),
- __end_(std::move(__other.__end_)),
- __cap_(std::move(__other.__cap_)),
- __alloc_(std::move(__other.__alloc_)) {
- __other.__begin_ = nullptr;
- __other.__end_ = nullptr;
- __other.__cap_ = nullptr;
- }
-
- // Capacity
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(__end_ - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __begin_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __begin_ == __end_;
- }
-
- // Access
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __allocator_ref() _NOEXCEPT {
- return __alloc_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const&
- __allocator_ref() const _NOEXCEPT {
- return __alloc_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__vector_layout& __x)
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __x.__begin_);
- std::swap(__end_, __x.__end_);
- std::swap(__cap_, __x.__cap_);
- std::__swap_allocator(__alloc_, __x.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_begin() const _NOEXCEPT {
- return __begin_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_capacity() const _NOEXCEPT {
- return __cap_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
- __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __end_;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
- return __end_ == __cap_;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __end;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
- __begin_ = __begin;
- __end_ = __begin_ + __size;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
- __end_ = __begin_ + __offset;
- }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
-
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
- __cap_ = __begin_ + __offset;
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
- return false;
- } else {
- if (__begin_ > __end_)
- return false;
- if (__begin_ == __cap_)
- return false;
- if (__end_ > __cap_)
- return false;
- }
- return true;
- }
-
-private:
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_);
-};
-#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
-
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
-class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
- using __base _LIBCPP_NODEBUG = __vector_layout<vector, _Tp, _Allocator>;
- using __self _LIBCPP_NODEBUG = vector;
- using __base::__allocator_ref;
- using __base::__end_pointer;
- using __base::__is_full;
- using __base::__raw_begin;
- using __base::__raw_capacity;
- using __base::__raw_sentinel;
- using __base::__remaining_capacity;
- using __base::__set_capacity;
- using __base::__set_sentinel;
- using __base::__set_valid_range;
- using typename __base::__alloc_traits;
- using typename __base::__sentinel_type;
- using typename __base::__split_buffer;
-
+class vector {
public:
- using value_type = _Tp;
- using allocator_type = _Allocator;
- using reference = typename __base::reference;
- using const_reference = typename __base::const_reference;
- using size_type = typename __base::size_type;
- using difference_type = typename __base::difference_type;
- using pointer = typename __base::pointer;
- using const_pointer = typename __base::const_pointer;
+ using value_type = _Tp;
+ using allocator_type = _Allocator;
+ using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename __alloc_traits::size_type;
+ using difference_type = typename __alloc_traits::difference_type;
+ using pointer = typename __alloc_traits::pointer;
+ using const_pointer = typename __alloc_traits::const_pointer;
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
// Users might provide custom allocators, and prior to C++20 we have no existing way to detect whether the allocator's
// pointer type is contiguous (though it has to be by the Standard). Using the wrapper type ensures the iterator is
@@ -425,8 +109,6 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using __base::__invariants;
-
// A vector contains the following members which may be trivially relocatable:
// - pointer: may be trivially relocatable, so it's checked
// - allocator_type: may be trivially relocatable, so it's checked
@@ -451,7 +133,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#else
noexcept
#endif
- : __base(__a) {
+ : __alloc_(__a) {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n) {
@@ -465,7 +147,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#if _LIBCPP_STD_VER >= 14
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit vector(size_type __n, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -487,7 +169,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
template <__enable_if_t<__is_allocator_v<_Allocator>, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
auto __guard = std::__make_exception_guard(__destroy_vector(*this));
if (__n > 0) {
__vallocate(__n);
@@ -510,7 +192,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
__init_with_sentinel(__first, __last);
}
@@ -531,7 +213,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(_ForwardIterator __first, _ForwardIterator __last, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
size_type __n = static_cast<size_type>(std::distance(__first, __last));
__init_with_size(__first, __last, __n);
}
@@ -540,7 +222,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr vector(
from_range_t, _Range&& __range, const allocator_type& __alloc = allocator_type())
- : __base(__alloc) {
+ : __alloc_(__alloc) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
auto __n = static_cast<size_type>(ranges::distance(__range));
__init_with_size(ranges::begin(__range), ranges::end(__range), __n);
@@ -557,10 +239,10 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __destroy_vector(vector& __vec) : __vec_(__vec) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() {
- if (__vec_.__raw_begin() != nullptr) {
+ if (__vec_.__begin_ != nullptr) {
__vec_.clear();
__vec_.__annotate_delete();
- __alloc_traits::deallocate(__vec_.__allocator_ref(), __vec_.__raw_begin(), __vec_.capacity());
+ __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity());
}
}
@@ -572,13 +254,13 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x)
- : __base(__alloc_traits::select_on_container_copy_construction(__x.__allocator_ref())) {
- __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
+ : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) {
+ __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(const vector& __x, const __type_identity_t<allocator_type>& __a)
- : __base(__a) {
- __init_with_size(__x.__raw_begin(), __x.__end_pointer(), __x.size());
+ : __alloc_(__a) {
+ __init_with_size(__x.__begin_, __x.__end_pointer(), __x.size());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector& operator=(const vector& __x);
@@ -589,7 +271,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
vector(initializer_list<value_type> __il, const allocator_type& __a)
- : __base(__a) {
+ : __alloc_(__a) {
__init_with_size(__il.begin(), __il.end(), __il.size());
}
@@ -652,17 +334,17 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return __allocator_ref();
+ return __alloc_;
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__raw_begin()));
+ return __make_iter(__add_alignment_assumption(__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__raw_begin()));
+ return __make_iter(__add_alignment_assumption(__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
return __make_iter(__add_alignment_assumption(__end_pointer()));
@@ -704,17 +386,30 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
//
// Capacity
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return __base::size();
+ return __size_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return __base::capacity();
+ return __cap_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __base::empty();
+ return __size_ == 0;
}
+#else
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
+ return static_cast<size_type>(__end_ - __begin_);
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
+ return static_cast<size_type>(__cap_ - __begin_);
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
+ return __begin_ == __end_;
+ }
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(__allocator_ref()), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(__alloc_), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -724,48 +419,62 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return __raw_begin()[__n];
+ return __begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__raw_begin();
+ return *__begin_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__raw_begin();
+ return *__begin_;
}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
- return __base::back();
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return __begin_[__size_ - 1];
+ }
+#else
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
- return __base::back();
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
+ return *(__end_ - 1);
}
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
//
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(__raw_begin());
+ return std::__to_address(__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(__raw_begin());
+ return std::__to_address(__begin_);
}
//
@@ -790,7 +499,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -802,12 +511,12 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
if (__len < __raw_capacity() - __raw_sentinel()) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
- __split_buffer __buffer(__recommend(size() + __len), size(), __allocator_ref());
+ __split_buffer __buffer(__recommend(size() + __len), size(), __alloc_);
__buffer.__construct_at_end_with_size(ranges::begin(__range), __len);
__swap_out_circular_buffer(__buffer);
}
} else {
- vector __buffer(__allocator_ref());
+ vector __buffer(__alloc_);
for (auto&& __val : __range)
__buffer.emplace_back(std::forward<decltype(__val)>(__val));
append_range(ranges::as_rvalue_view(__buffer));
@@ -873,7 +582,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(__raw_begin());
+ __base_destruct_at_end(__begin_);
__annotate_shrink(__old_size);
}
@@ -887,10 +596,151 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
#endif
{
- __base::swap(__other);
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __other.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(__begin_, __other.__begin_);
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ std::swap(__size_, __other.__size_);
+#else
+ std::swap(__end_, __other.__end_);
+#endif
+ std::swap(__cap_, __other.__cap_);
+ std::__swap_allocator(__alloc_, __other.__alloc_);
+ }
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+public:
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ != 0 || __cap_ != 0)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
+ }
+ return true;
+ }
+private:
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ return __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __size_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __end - __begin_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __size_ = __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ __size_ = __size;
}
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __size_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ __cap_ = static_cast<size_type>(__pos - __begin_);
+ }
+
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
+#else
+public:
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+ }
private:
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
+ return __end_;
+ }
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ return __end_ == __cap_;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __end;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ __begin_ = __begin;
+ __end_ = __begin_ + __size;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ __end_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ __cap_ = __begin_ + __offset;
+ }
+
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
+ return __cap_;
+ }
+
// Allocate space for __n objects
// throws length_error if __n > max_size()
// throws (probably bad_alloc) if memory run out
@@ -903,7 +753,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(__allocator_ref(), __n);
+ auto __allocation = std::__allocate_at_least(__alloc_, __n);
__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__set_capacity(__allocation.count);
__annotate_new(0);
@@ -954,7 +804,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), *__first);
+ __temp_value<value_type, _Allocator> __tmp(__alloc_, *__first);
*__position = std::move(__tmp.get());
}
}
@@ -992,7 +842,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(__raw_begin()),
+ std::__wrap_iter<pointer>(__begin_),
std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
@@ -1004,7 +854,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(__raw_begin()),
+ std::__wrap_iter<const_pointer>(__begin_),
std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
@@ -1068,7 +918,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
__v_.__set_sentinel(__pos_);
if (__pos_ != __new_end_) {
- __v_.__annotate_shrink(__new_end_ - __v_.__raw_begin());
+ __v_.__annotate_shrink(__new_end_ - __v_.__begin_);
}
}
@@ -1083,7 +933,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(__allocator_ref(), std::__to_address(--__soon_to_be_end));
+ __alloc_traits::destroy(__alloc_, std::__to_address(--__soon_to_be_end));
__set_sentinel(__new_last);
}
@@ -1102,21 +952,21 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (__allocator_ref() != __c.__allocator_ref()) {
+ if (__alloc_ != __c.__alloc_) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __alloc_traits::deallocate(__alloc_, __begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<__sentinel_type>(0));
}
- __allocator_ref() = __c.__allocator_ref();
+ __alloc_ = __c.__alloc_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __allocator_ref() = std::move(__c.__allocator_ref());
+ __alloc_ = std::move(__c.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -1137,7 +987,7 @@ class vector : __vector_layout<vector<_Tp, _Allocator>, _Tp, _Allocator> {
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_layouts(__split_buffer& __sb) {
- auto __vector_begin = __raw_begin();
+ auto __vector_begin = __begin_;
auto __vector_sentinel = __raw_sentinel();
auto __vector_cap = __raw_capacity();
@@ -1174,7 +1024,7 @@ template <ranges::input_range _Range,
vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
#endif
-// __swap_out_circular_buffer relocates the objects in [__raw_begin(), size()) into the front of __v and swaps the
+// __swap_out_circular_buffer relocates the objects in [__begin_, size()) into the front of __v and swaps the
// buffers of *this and __v. It is assumed that __v provides space for exactly size() objects in the front. This
// function has a strong exception guarantee.
template <class _Tp, class _Allocator>
@@ -1182,8 +1032,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
- std::__to_address(__raw_begin()),
+ __alloc_,
+ std::__to_address(__begin_),
std::__to_address(__end_pointer()),
std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
@@ -1195,10 +1045,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_new(size());
}
-// __swap_out_circular_buffer relocates the objects in [__raw_begin(), __p) into the front of __v, the objects in
+// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
// [__p, end()) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __raw_begin()) objects in the front and space for at least (size() - __p) objects in the back. This
-// function has a strong exception guarantee if __raw_begin() == __p || size() == __p.
+// exactly (__p - __begin_) objects in the front and space for at least (size() - __p) objects in the back. This
+// function has a strong exception guarantee if __begin_ == __p || size() == __p.
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) {
@@ -1206,18 +1056,18 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
pointer __ret = __v.begin();
pointer __end = __end_pointer();
- // Relocate [__p, __end) first to avoid having a hole in [__raw_begin(), __end)
- // in case something in [__raw_begin(), __p) throws.
+ // Relocate [__p, __end) first to avoid having a hole in [__begin_, __end)
+ // in case something in [__begin_, __p) throws.
std::__uninitialized_allocator_relocate(
- __allocator_ref(), std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ __alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
__set_sentinel(
__raw_sentinel() - __relocated_so_far); // The objects in [__p, __end_) have been destroyed by relocating them.
- auto __new_begin = __v.begin() - (__p - __raw_begin());
+ auto __new_begin = __v.begin() - (__p - __begin_);
std::__uninitialized_allocator_relocate(
- __allocator_ref(), std::__to_address(__raw_begin()), std::__to_address(__p), std::__to_address(__new_begin));
+ __alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
@@ -1229,10 +1079,10 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (__raw_begin() != nullptr) {
+ if (__begin_ != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__allocator_ref(), __raw_begin(), capacity());
+ __alloc_traits::deallocate(__alloc_, __begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<size_type>(0));
}
@@ -1261,7 +1111,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos));
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos));
}
}
@@ -1277,7 +1127,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), __x);
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos), __x);
}
}
@@ -1287,7 +1137,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
__tx.__pos_ =
- std::__uninitialized_allocator_copy(__allocator_ref(), std::move(__first), std::move(__last), __tx.__pos_);
+ std::__uninitialized_allocator_copy(__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1297,8 +1147,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
#else
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
#endif
- : __base(std::move(__x.__allocator_ref())) {
- __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ : __alloc_(std::move(__x.__alloc_)) {
+ __set_valid_range(__x.__begin_, __x.__raw_sentinel());
__set_capacity(__x.__raw_capacity());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
@@ -1307,9 +1157,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_type>& __a)
- : __base(__a) {
- if (__a == __x.__allocator_ref()) {
- __set_valid_range(__x.__raw_begin(), __x.__raw_sentinel());
+ : __alloc_(__a) {
+ if (__a == __x.__alloc_) {
+ __set_valid_range(__x.__begin_, __x.__raw_sentinel());
__set_capacity(__x.__raw_capacity());
__x.__set_valid_range(nullptr, static_cast<size_type>(0));
__x.__set_capacity(static_cast<size_type>(0));
@@ -1322,7 +1172,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (__allocator_ref() != __c.__allocator_ref()) {
+ if (__alloc_ != __c.__alloc_) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1334,7 +1184,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
__vdeallocate();
__move_assign_alloc(__c); // this can throw
- __set_valid_range(__c.__raw_begin(), __c.__raw_sentinel());
+ __set_valid_range(__c.__begin_, __c.__raw_sentinel());
__set_capacity(__c.__raw_capacity());
__c.__set_valid_range(nullptr, static_cast<size_type>(0));
__c.__set_capacity(static_cast<size_type>(0));
@@ -1345,7 +1195,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato
vector<_Tp, _Allocator>::operator=(const vector& __x) {
if (this != std::addressof(__x)) {
__copy_assign_alloc(__x);
- assign(__x.__raw_begin(), __x.__end_pointer());
+ assign(__x.__begin_, __x.__end_pointer());
}
return *this;
}
@@ -1354,7 +1204,7 @@ template <class _Tp, class _Allocator>
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_sentinel(_Iterator __first, _Sentinel __last) {
- pointer __cur = __raw_begin();
+ pointer __cur = __begin_;
pointer __end = __end_pointer();
for (; __first != __last && __cur != __end; ++__first, (void)++__cur)
*__cur = *__first;
@@ -1374,10 +1224,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
auto const __size = size();
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __raw_begin()).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, __raw_begin()).second;
+ pointer __m = std::__copy(std::move(__first), __last, __begin_).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1391,11 +1241,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(__raw_begin(), std::min(__n, __s), __u);
+ std::fill_n(__begin_, std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(__raw_begin() + __n);
+ this->__destruct_at_end(__begin_ + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1408,7 +1258,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer __v(__n, size(), __allocator_ref());
+ __split_buffer __v(__n, size(), __alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1419,7 +1269,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer __v(size(), size(), __allocator_ref());
+ __split_buffer __v(size(), size(), __alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1436,10 +1286,10 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer __v(__recommend(size() + 1), size(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), size(), __alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
return __raw_sentinel();
@@ -1493,7 +1343,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = __raw_begin() + __ps;
+ pointer __p = __begin_ + __ps;
this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1502,7 +1352,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = __raw_begin() + (__first - begin());
+ pointer __p = __begin_ + (__first - begin());
if (__first != __last) {
this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
@@ -1518,7 +1368,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
pointer __i = __from_s + __n;
_ConstructTransaction __tx(*this, __from_e - __i);
for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
- __alloc_traits::construct(__allocator_ref(), std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(__alloc_, std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1527,7 +1377,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1540,7 +1390,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1550,7 +1400,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1560,7 +1410,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1571,18 +1421,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(__allocator_ref(), std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(__alloc_, std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1592,7 +1442,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (__n > 0) {
if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
@@ -1611,7 +1461,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1624,7 +1474,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = __raw_begin() + __off;
+ pointer __p = __begin_ + __off;
pointer __old_last = __end_pointer();
for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
@@ -1632,15 +1482,15 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
if (__first == __last)
(void)std::rotate(__p, __old_last, __end_pointer());
else {
- __split_buffer __v(__allocator_ref());
+ __split_buffer __v(__alloc_);
pointer __end = __end_pointer();
auto __guard = std::__make_exception_guard(
- _AllocatorDestroyRangeReverse<allocator_type, pointer>(__allocator_ref(), __old_last, __end));
+ _AllocatorDestroyRangeReverse<allocator_type, pointer>(__alloc_, __old_last, __end));
__v.__construct_at_end_with_sentinel(std::move(__first), std::move(__last));
__split_buffer __merged(
- __recommend(size() + __v.size()), __off, __allocator_ref()); // has `__off` positions available at the front
+ __recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
+ __alloc_,
std::__to_address(__old_last),
std::__to_address(__end_pointer()),
std::__to_address(__merged.end()));
@@ -1649,7 +1499,7 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
__set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __allocator_ref(),
+ __alloc_,
std::__to_address(__v.begin()),
std::__to_address(__v.end()),
std::__to_address(__merged.end()));
@@ -1665,7 +1515,7 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = __raw_begin() + (__position - begin());
+ pointer __p = __begin_ + (__position - begin());
if (__n > 0) {
if (__n <= static_cast<difference_type>(__remaining_capacity())) {
pointer __end = __end_pointer();
@@ -1691,7 +1541,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __raw_begin(), __allocator_ref());
+ __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1706,12 +1556,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__raw_begin() + __new_size);
+ this->__destruct_at_end(__begin_ + __new_size);
}
}
@@ -1722,12 +1572,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity())
__construct_at_end(__new_size - __current_size, __x);
else {
- __split_buffer __v(__recommend(__new_size), __current_size, __allocator_ref());
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size, __x);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__raw_begin() + __new_size);
+ this->__destruct_at_end(__begin_ + __new_size);
}
}
>From f502629b7f53444056ef164cb057e2d321e1ea05 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 22:48:54 +0000
Subject: [PATCH 3/8] further reduces the diff
0580dea significantly reduced the diff by returning the stable ABI code
to its original location. `__vector_base` did away with using `this->`
for most things, since it's largely redundant, but these were left out
in 0580dea. This commit adds most of those back.
---
libcxx/include/__vector/vector.h | 194 ++++++++++++++++---------------
1 file changed, 100 insertions(+), 94 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 29cd205aeb8da..28465a6b4c44d 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -334,17 +334,17 @@ class vector {
#endif
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT {
- return __alloc_;
+ return this->__alloc_;
}
//
// Iterators
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
- return __make_iter(__add_alignment_assumption(__begin_));
+ return __make_iter(__add_alignment_assumption(this->__begin_));
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT {
return __make_iter(__add_alignment_assumption(__end_pointer()));
@@ -398,18 +398,18 @@ class vector {
}
#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
- return static_cast<size_type>(__end_ - __begin_);
+ return static_cast<size_type>(this->__end_ - this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
- return static_cast<size_type>(__cap_ - __begin_);
+ return static_cast<size_type>(this->__cap_ - this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT {
- return __begin_ == __end_;
+ return this->__begin_ == this->__end_;
}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
- return std::min<size_type>(__alloc_traits::max_size(__alloc_), numeric_limits<difference_type>::max());
+ return std::min<size_type>(__alloc_traits::max_size(this->__alloc_), numeric_limits<difference_type>::max());
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
@@ -419,31 +419,31 @@ class vector {
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
if (__n >= size())
this->__throw_out_of_range();
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __n) const {
if (__n >= size())
this->__throw_out_of_range();
- return __begin_[__n];
+ return this->__begin_[__n];
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__begin_;
+ return *this->__begin_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
- return *__begin_;
+ return *this->__begin_;
}
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -458,11 +458,11 @@ class vector {
#else
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
+ return *(this->__end_ - 1);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
- return *(__end_ - 1);
+ return *(this->__end_ - 1);
}
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
@@ -470,11 +470,11 @@ class vector {
// [vector.data], data access
//
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI value_type* data() _NOEXCEPT {
- return std::__to_address(__begin_);
+ return std::__to_address(this->__begin_);
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const value_type* data() const _NOEXCEPT {
- return std::__to_address(__begin_);
+ return std::__to_address(this->__begin_);
}
//
@@ -499,7 +499,7 @@ class vector {
_LIBCPP_ASSERT_INTERNAL(
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
_ConstructTransaction __tx(*this, 1);
- __alloc_traits::construct(__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
++__tx.__pos_;
}
@@ -582,7 +582,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
size_type __old_size = size();
- __base_destruct_at_end(__begin_);
+ __base_destruct_at_end(this->__begin_);
__annotate_shrink(__old_size);
}
@@ -610,18 +610,10 @@ class vector {
std::__swap_allocator(__alloc_, __other.__alloc_);
}
+
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-public:
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__size_ != 0 || __cap_ != 0)
- return false;
- } else {
- if (__size_ > __cap_)
- return false;
- }
- return true;
- }
private:
using __sentinel_type _LIBCPP_NODEBUG = size_type;
using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
@@ -671,21 +663,6 @@ class vector {
size_type __cap_ = 0;
[[no_unique_address]] allocator_type __alloc_;
#else
-public:
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
- return false;
- } else {
- if (__begin_ > __end_)
- return false;
- if (__begin_ == __cap_)
- return false;
- if (__end_ > __cap_)
- return false;
- }
- return true;
- }
private:
using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
using __sentinel_type _LIBCPP_NODEBUG = pointer;
@@ -753,7 +730,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
if (__n > max_size())
this->__throw_length_error();
- auto __allocation = std::__allocate_at_least(__alloc_, __n);
+ auto __allocation = std::__allocate_at_least(this->__alloc_, __n);
__set_valid_range(__allocation.ptr, static_cast<size_type>(0));
__set_capacity(__allocation.count);
__annotate_new(0);
@@ -804,7 +781,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
__insert_assign_n_unchecked(_Iterator __first, difference_type __n, pointer __position) {
for (pointer __end_position = __position + __n; __position != __end_position; ++__position, (void)++__first) {
- __temp_value<value_type, _Allocator> __tmp(__alloc_, *__first);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc_, *__first);
*__position = std::move(__tmp.get());
}
}
@@ -842,7 +819,7 @@ class vector {
// a laxer approach.
return std::__make_bounded_iter(
std::__wrap_iter<pointer>(__p),
- std::__wrap_iter<pointer>(__begin_),
+ std::__wrap_iter<pointer>(this->__begin_),
std::__wrap_iter<pointer>(__raw_capacity()));
#else
return iterator(__p);
@@ -854,7 +831,7 @@ class vector {
// Bound the iterator according to the capacity, rather than the size.
return std::__make_bounded_iter(
std::__wrap_iter<const_pointer>(__p),
- std::__wrap_iter<const_pointer>(__begin_),
+ std::__wrap_iter<const_pointer>(this->__begin_),
std::__wrap_iter<const_pointer>(__raw_capacity()));
#else
return const_iterator(__p);
@@ -933,7 +910,7 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
pointer __soon_to_be_end = __end_pointer();
while (__new_last != __soon_to_be_end)
- __alloc_traits::destroy(__alloc_, std::__to_address(--__soon_to_be_end));
+ __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end));
__set_sentinel(__new_last);
}
@@ -952,21 +929,21 @@ class vector {
[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) {
- if (__alloc_ != __c.__alloc_) {
+ if (this->__alloc_ != __c.__alloc_) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__alloc_, __begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<__sentinel_type>(0));
}
- __alloc_ = __c.__alloc_;
+ this->__alloc_ = __c.__alloc_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
- __alloc_ = std::move(__c.__alloc_);
+ this->__alloc_ = std::move(__c.__alloc_);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {}
@@ -1032,7 +1009,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- __alloc_,
+ this->__alloc_,
std::__to_address(__begin_),
std::__to_address(__end_pointer()),
std::__to_address(__new_begin));
@@ -1059,7 +1036,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
// Relocate [__p, __end) first to avoid having a hole in [__begin_, __end)
// in case something in [__begin_, __p) throws.
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
+ this->__alloc_, std::__to_address(__p), std::__to_address(__end), std::__to_address(__v.end()));
auto __relocated_so_far = __end - __p;
__v.__set_sentinel(__v.end() + __relocated_so_far);
__set_sentinel(
@@ -1067,7 +1044,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
auto __new_begin = __v.begin() - (__p - __begin_);
std::__uninitialized_allocator_relocate(
- __alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
+ this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.size() + size());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
@@ -1079,10 +1056,10 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT {
- if (__begin_ != nullptr) {
+ if (this->__begin_ != nullptr) {
clear();
__annotate_delete();
- __alloc_traits::deallocate(__alloc_, __begin_, capacity());
+ __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity());
__set_valid_range(nullptr, static_cast<size_type>(0));
__set_capacity(static_cast<size_type>(0));
}
@@ -1111,7 +1088,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(__alloc_, std::__to_address(__pos));
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos));
}
}
@@ -1127,7 +1104,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
_ConstructTransaction __tx(*this, __n);
const_pointer __new_end = __tx.__new_end_;
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
- __alloc_traits::construct(__alloc_, std::__to_address(__pos), __x);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), __x);
}
}
@@ -1136,8 +1113,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
_ConstructTransaction __tx(*this, __n);
- __tx.__pos_ =
- std::__uninitialized_allocator_copy(__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
+ __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
}
template <class _Tp, class _Allocator>
@@ -1172,7 +1148,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t<allocator_
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
_NOEXCEPT_(__alloc_traits::is_always_equal::value) {
- if (__alloc_ != __c.__alloc_) {
+ if (this->__alloc_ != __c.__alloc_) {
typedef move_iterator<iterator> _Ip;
assign(_Ip(__c.begin()), _Ip(__c.end()));
} else
@@ -1224,10 +1200,10 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
if (__new_size <= capacity()) {
if (__new_size > size()) {
auto const __size = size();
- auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, __begin_).first;
+ auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
- pointer __m = std::__copy(std::move(__first), __last, __begin_).second;
+ pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
this->__destruct_at_end(__m);
}
} else {
@@ -1241,11 +1217,11 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::assign(size_type __n, const_reference __u) {
if (__n <= capacity()) {
size_type __s = size();
- std::fill_n(__begin_, std::min(__n, __s), __u);
+ std::fill_n(this->__begin_, std::min(__n, __s), __u);
if (__n > __s)
__construct_at_end(__n - __s, __u);
else
- this->__destruct_at_end(__begin_ + __n);
+ this->__destruct_at_end(this->__begin_ + __n);
} else {
__vdeallocate();
__vallocate(__recommend(static_cast<size_type>(__n)));
@@ -1258,7 +1234,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __
if (__n > capacity()) {
if (__n > max_size())
this->__throw_length_error();
- __split_buffer __v(__n, size(), __alloc_);
+ __split_buffer __v(__n, size(), this->__alloc_);
__swap_out_circular_buffer(__v);
}
}
@@ -1269,7 +1245,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE
#if _LIBCPP_HAS_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_EXCEPTIONS
- __split_buffer __v(size(), size(), __alloc_);
+ __split_buffer __v(size(), size(), this->__alloc_);
// The Standard mandates shrink_to_fit() does not increase the capacity.
// With equal capacity keep the existing buffer. This avoids extra work
// due to swapping the elements.
@@ -1286,10 +1262,10 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::__sentinel_type
vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) {
- __split_buffer __v(__recommend(size() + 1), size(), __alloc_);
+ __split_buffer __v(__recommend(size() + 1), size(), this->__alloc_);
// __v.emplace_back(std::forward<_Args>(__args)...);
pointer __end = __v.end();
- __alloc_traits::construct(__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__end), std::forward<_Args>(__args)...);
__v.__set_sentinel(++__end);
__swap_out_circular_buffer(__v);
return __raw_sentinel();
@@ -1343,7 +1319,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
difference_type __ps = __position - cbegin();
- pointer __p = __begin_ + __ps;
+ pointer __p = this->__begin_ + __ps;
this->__destruct_at_end(std::move(__p + 1, __end_pointer(), __p));
return __make_iter(__p);
}
@@ -1352,7 +1328,7 @@ template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
- pointer __p = __begin_ + (__first - begin());
+ pointer __p = this->__begin_ + (__first - begin());
if (__first != __last) {
this->__destruct_at_end(std::move(__p + (__last - __first), __end_pointer(), __p));
}
@@ -1368,7 +1344,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
pointer __i = __from_s + __n;
_ConstructTransaction __tx(*this, __from_e - __i);
for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
- __alloc_traits::construct(__alloc_, std::__to_address(__pos), std::move(*__i));
+ __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), std::move(*__i));
}
}
std::move_backward(__from_s, __from_s + __n, __old_last);
@@ -1377,7 +1353,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1390,7 +1366,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
*__p = *__xr;
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(__x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1400,7 +1376,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
@@ -1410,7 +1386,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) {
*__p = std::move(__x);
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::move(__x));
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1421,18 +1397,18 @@ template <class _Tp, class _Allocator>
template <class... _Args>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (!__is_full()) {
pointer __end = __end_pointer();
if (__p == __end) {
__emplace_back_assume_capacity(std::forward<_Args>(__args)...);
} else {
- __temp_value<value_type, _Allocator> __tmp(__alloc_, std::forward<_Args>(__args)...);
+ __temp_value<value_type, _Allocator> __tmp(this->__alloc_, std::forward<_Args>(__args)...);
__move_range(__p, __end, __p + 1);
*__p = std::move(__tmp.get());
}
} else {
- __split_buffer __v(__recommend(size() + 1), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_);
__v.emplace_back(std::forward<_Args>(__args)...);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1442,7 +1418,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) {
template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (__n > 0) {
if (__n <= __remaining_capacity()) {
size_type __old_n = __n;
@@ -1461,7 +1437,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
std::fill_n(__p, __n, *__xr);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end(__n, __x);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1474,7 +1450,7 @@ template <class _InputIterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) {
difference_type __off = __position - begin();
- pointer __p = __begin_ + __off;
+ pointer __p = this->__begin_ + __off;
pointer __old_last = __end_pointer();
for (; !__is_full() && __first != __last; ++__first)
__emplace_back_assume_capacity(*__first);
@@ -1515,7 +1491,7 @@ template <class _AlgPolicy, class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::__insert_with_size(
const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n) {
- pointer __p = __begin_ + (__position - begin());
+ pointer __p = this->__begin_ + (__position - begin());
if (__n > 0) {
if (__n <= static_cast<difference_type>(__remaining_capacity())) {
pointer __end = __end_pointer();
@@ -1541,7 +1517,7 @@ vector<_Tp, _Allocator>::__insert_with_size(
__insert_assign_n_unchecked<_AlgPolicy>(std::move(__first), __n, __p);
}
} else {
- __split_buffer __v(__recommend(size() + __n), __p - __begin_, __alloc_);
+ __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_);
__v.__construct_at_end_with_size(std::move(__first), __n);
__p = __swap_out_circular_buffer(__v, __p);
}
@@ -1556,12 +1532,12 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, this->__alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ + __new_size);
}
}
@@ -1577,16 +1553,46 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
__swap_out_circular_buffer(__v);
}
} else if (__current_size > __new_size) {
- this->__destruct_at_end(__begin_ + __new_size);
+ this->__destruct_at_end(this->__begin_ + __new_size);
+ }
+}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template<class _Tp, class _Allocator>
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ if (__begin_ == nullptr) {
+ if (__size_ != 0 || __cap_ != 0)
+ return false;
+ } else {
+ if (__size_ > __cap_)
+ return false;
}
+ return true;
}
+#else
+template<class _Tp, class _Allocator>
+[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ if (__begin_ == nullptr) {
+ if (__end_ != nullptr || __cap_ != nullptr)
+ return false;
+ } else {
+ if (__begin_ > __end_)
+ return false;
+ if (__begin_ == __cap_)
+ return false;
+ if (__end_ > __cap_)
+ return false;
+ }
+ return true;
+}
+#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
#if _LIBCPP_STD_VER >= 20
-template <class _Allocator>
-inline constexpr bool __format::__enable_insertable<vector<char, _Allocator>> = true;
+template <>
+inline constexpr bool __format::__enable_insertable<vector<char>> = true;
# if _LIBCPP_HAS_WIDE_CHARACTERS
-template <class _Allocator>
-inline constexpr bool __format::__enable_insertable<vector<wchar_t, _Allocator>> = true;
+template <>
+inline constexpr bool __format::__enable_insertable<vector<wchar_t>> = true;
# endif
#endif // _LIBCPP_STD_VER >= 20
>From 935405c3d732684229ed15ba4721d0fcb4fde9cb Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Tue, 13 Jan 2026 23:25:20 +0000
Subject: [PATCH 4/8] fixes breaks from generic-cxx20
---
libcxx/include/__vector/vector.h | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 28465a6b4c44d..ea56b3ecc65b3 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -676,7 +676,7 @@ class vector {
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __end_;
+ return __cap_ - __end_;
}
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
@@ -695,16 +695,12 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
__end_ = __begin_ + __offset;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
- __cap_ = __begin_ + __offset;
- }
-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
__cap_ = __begin_ + __offset;
}
>From 970d4588c0e261f762b47258b6bc620b8825fdaf Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 14 Jan 2026 01:38:47 +0000
Subject: [PATCH 5/8] further reduces diff
---
libcxx/include/__split_buffer | 3 +-
libcxx/include/__vector/vector.h | 187 ++++++++++++++++---------------
2 files changed, 99 insertions(+), 91 deletions(-)
diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index 1b1492dadaddc..da26a6e74935a 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -310,7 +310,8 @@ public:
return __begin_[__size_ - 1];
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(__split_buffer_size_layout& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __swap_without_allocator(__split_buffer_size_layout& __other) _NOEXCEPT {
std::swap(__front_cap_, __other.__front_cap_);
std::swap(__begin_, __other.__begin_);
std::swap(__cap_, __other.__cap_);
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index ea56b3ecc65b3..2ffa67453adc9 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -87,6 +87,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
public:
+ ///
+ /// Types
+ ///
using value_type = _Tp;
using allocator_type = _Allocator;
using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
@@ -589,97 +592,87 @@ class vector {
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const_reference __x);
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector& __other)
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(vector&)
#if _LIBCPP_STD_VER >= 14
- _NOEXCEPT
+ _NOEXCEPT;
#else
- _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
#endif
- {
- _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
- __alloc_traits::propagate_on_container_swap::value || __alloc_ == __other.__alloc_,
- "vector::swap: Either propagate_on_container_swap must be true"
- " or the allocators must compare equal");
- std::swap(__begin_, __other.__begin_);
-#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
- std::swap(__size_, __other.__size_);
-#else
- std::swap(__end_, __other.__end_);
-#endif
- std::swap(__cap_, __other.__cap_);
- std::__swap_allocator(__alloc_, __other.__alloc_);
- }
-
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+
private:
- using __sentinel_type _LIBCPP_NODEBUG = size_type;
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = size_type;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
return __size_;
- }
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __begin_ + __size_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __begin_ + __size_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __size_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __size_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
return __size_ == __cap_;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, pointer __end) _NOEXCEPT {
__begin_ = __begin;
- __size_ = __end - __begin_;
- }
+ __size_ = __end - __begin_;
+ }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
__begin_ = __begin;
__size_ = __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __size) _NOEXCEPT {
__size_ = __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __pos) _NOEXCEPT {
__size_ = static_cast<size_type>(__pos - __begin_);
- }
+ }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __pos) _NOEXCEPT {
__cap_ = static_cast<size_type>(__pos - __begin_);
- }
+ }
- pointer __begin_ = nullptr;
- size_type __size_ = 0;
- size_type __cap_ = 0;
- [[no_unique_address]] allocator_type __alloc_;
+ pointer __begin_ = nullptr;
+ size_type __size_ = 0;
+ size_type __cap_ = 0;
+ [[no_unique_address]] allocator_type __alloc_;
#else
+
private:
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
- using __sentinel_type _LIBCPP_NODEBUG = pointer;
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+ using __sentinel_type _LIBCPP_NODEBUG = pointer;
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
return __end_;
}
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
- return __end_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __end_pointer() const _NOEXCEPT {
+ return __end_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __remaining_capacity() const _NOEXCEPT {
- return __cap_ - __end_;
- }
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type
+ __remaining_capacity() const _NOEXCEPT {
+ return __cap_ - __end_;
+ }
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __is_full() const _NOEXCEPT {
return __end_ == __cap_;
}
@@ -688,29 +681,31 @@ class vector {
__end_ = __end;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
+ __set_valid_range(pointer __begin, size_type __size) _NOEXCEPT {
__begin_ = __begin;
__end_ = __begin_ + __size;
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __end) _NOEXCEPT { __end_ = __end; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __offset) _NOEXCEPT {
__end_ = __begin_ + __offset;
- }
+ }
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __cap) _NOEXCEPT { __cap_ = __cap; }
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __offset) _NOEXCEPT {
__cap_ = __begin_ + __offset;
}
- pointer __begin_ = nullptr;
- pointer __end_ = nullptr;
- _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
+ pointer __begin_ = nullptr;
+ pointer __end_ = nullptr;
+ _LIBCPP_COMPRESSED_PAIR(pointer, __cap_ = nullptr, allocator_type, __alloc_);
#endif // _LIBCPP_ABI_SIZE_BASED_VECTOR
- [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20
+ _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
return __cap_;
}
@@ -834,8 +829,7 @@ class vector {
#endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
}
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
- __swap_out_circular_buffer(__split_buffer& __v);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_out_circular_buffer(__split_buffer& __v);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer
__swap_out_circular_buffer(__split_buffer& __v, pointer __p);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
@@ -851,7 +845,8 @@ class vector {
}
template <class... _Args>
- _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __emplace_back_slow_path(_Args&&... __args);
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI inline __sentinel_type
+ __emplace_back_slow_path(_Args&&... __args);
// The following functions are no-ops outside of AddressSanitizer mode.
// We call annotations for every allocator, unless explicitly disabled.
@@ -1005,13 +1000,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__swap_out_circular_
__annotate_delete();
auto __new_begin = __v.begin() - size();
std::__uninitialized_allocator_relocate(
- this->__alloc_,
- std::__to_address(__begin_),
- std::__to_address(__end_pointer()),
- std::__to_address(__new_begin));
+ this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_pointer()), std::__to_address(__new_begin));
__v.__set_valid_range(__new_begin, __v.end());
__set_sentinel(static_cast<size_type>(0)); // All the objects have been destroyed by relocating them.
- // __v.__size_ += __size_;
__swap_layouts(__v);
__v.__set_data(__v.begin());
@@ -1194,8 +1185,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last, difference_type __n) {
size_type __new_size = static_cast<size_type>(__n);
if (__new_size <= capacity()) {
- if (__new_size > size()) {
- auto const __size = size();
+ auto const __size = size();
+ if (__new_size > __size) {
auto __mid = std::__copy_n<_AlgPolicy>(std::move(__first), __size, this->__begin_).first;
__construct_at_end(std::move(__mid), std::move(__last), __new_size - __size);
} else {
@@ -1462,19 +1453,13 @@ vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _Inpu
__split_buffer __merged(
__recommend(size() + __v.size()), __off, __alloc_); // has `__off` positions available at the front
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__old_last),
- std::__to_address(__end_pointer()),
- std::__to_address(__merged.end()));
+ __alloc_, std::__to_address(__old_last), std::__to_address(__end_pointer()), std::__to_address(__merged.end()));
__guard.__complete(); // Release the guard once objects in [__old_last_, __end_pointer()) have been successfully
// relocated.
__merged.__set_sentinel(__merged.end() + (__end_pointer() - __old_last));
__set_sentinel(__old_last);
std::__uninitialized_allocator_relocate(
- __alloc_,
- std::__to_address(__v.begin()),
- std::__to_address(__v.end()),
- std::__to_address(__merged.end()));
+ __alloc_, std::__to_address(__v.begin()), std::__to_address(__v.end()), std::__to_address(__merged.end()));
__merged.__set_sentinel(__merged.size() + __v.size());
__v.__set_sentinel(__v.begin());
__p = __swap_out_circular_buffer(__merged, __p);
@@ -1528,7 +1513,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
if (__new_size <= capacity()) {
__construct_at_end(__new_size - __current_size);
} else {
- __split_buffer __v(__recommend(__new_size), __current_size, this->__alloc_);
+ __split_buffer __v(__recommend(__new_size), __current_size, __alloc_);
__v.__construct_at_end(__new_size - __current_size);
__swap_out_circular_buffer(__v);
}
@@ -1553,9 +1538,31 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::resize(size_type __n
}
}
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x)
+#if _LIBCPP_STD_VER >= 14
+ _NOEXCEPT
+#else
+ _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>)
+#endif
+{
+ _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
+ __alloc_traits::propagate_on_container_swap::value || __alloc_ == __x.__alloc_,
+ "vector::swap: Either propagate_on_container_swap must be true"
+ " or the allocators must compare equal");
+ std::swap(this->__begin_, __x.__begin_);
#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
-template<class _Tp, class _Allocator>
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
+ std::swap(this->__size_, __x.__size_);
+#else
+ std::swap(this->__end_, __x.__end_);
+#endif
+ std::swap(this->__cap_, __x.__cap_);
+ std::__swap_allocator(this->__alloc_, __x.__alloc_);
+}
+
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
if (__begin_ == nullptr) {
if (__size_ != 0 || __cap_ != 0)
return false;
@@ -1566,17 +1573,17 @@ template<class _Tp, class _Allocator>
return true;
}
#else
-template<class _Tp, class _Allocator>
-[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool vector<_Tp, _Allocator>::__invariants() const {
- if (__begin_ == nullptr) {
- if (__end_ != nullptr || __cap_ != nullptr)
+template <class _Tp, class _Allocator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const {
+ if (this->__begin_ == nullptr) {
+ if (this->__end_ != nullptr || this->__cap_ != nullptr)
return false;
} else {
- if (__begin_ > __end_)
+ if (this->__begin_ > this->__end_)
return false;
- if (__begin_ == __cap_)
+ if (this->__begin_ == this->__cap_)
return false;
- if (__end_ > __cap_)
+ if (this->__end_ > this->__cap_)
return false;
}
return true;
>From c87e88382d31e74a946bbc3f58c213dae1324d15 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Wed, 14 Jan 2026 02:35:00 +0000
Subject: [PATCH 6/8] gets GDB pretty-printer working
---
libcxx/utils/gdb/libcxx/printers.py | 32 ++++++++++++++---------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/libcxx/utils/gdb/libcxx/printers.py b/libcxx/utils/gdb/libcxx/printers.py
index 1bfdd718e36bc..83df6be78a1bb 100644
--- a/libcxx/utils/gdb/libcxx/printers.py
+++ b/libcxx/utils/gdb/libcxx/printers.py
@@ -13,7 +13,6 @@
from __future__ import print_function
import re
-import sys
import gdb
import gdb.printing
@@ -352,28 +351,29 @@ def __init__(self, val):
"""Set val, length, capacity, and iterator for bool and normal vectors."""
self.val = val
self.typename = _remove_generics(_prettify_typename(val.type))
+ begin = self.val["__begin_"]
if self.val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL:
- begin = self.val["__begin_"]
self.typename += "<bool>"
self.length = self.val["__size_"]
bits_per_word = self.val["__bits_per_word"]
self.capacity = self.val["__cap_"] * bits_per_word
self.iterator = self._VectorBoolIterator(begin, self.length, bits_per_word)
else:
- for i in val.type.fields():
- if i.is_base_class:
- base = val[i]
- break
-
- begin = base["__begin_"]
- end = base["__end_"]
- self.length = end - begin
- for i in base.type.fields():
- if i.name == "__cap_":
- self.capacity = base["__cap_"] - begin
- elif i.name == None:
- self.capacity = base[i]["__cap_"] - begin
- break
+ cap = self.val["__cap_"]
+
+ # We test for integers because `vector<T>::size_type` is required to
+ # be an unsigned integer, whereas `vector<T>::pointer` can be any
+ # type that satisfies the Cpp17NullablePointer requirements.
+ if cap.type.strip_typedefs().code == gdb.TYPE_CODE_INT:
+ size = self.val["__size_"]
+ self.length = size
+ self.capacity = cap
+ end = begin + size
+ else:
+ end = self.val["__end_"]
+ self.length = end - begin
+ self.capacity = cap - begin
+
self.iterator = self._VectorIterator(begin, end)
def to_string(self):
>From 44adc2d0c03ea421871d7a9b2aaa178ad828b1b7 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 15 Jan 2026 01:10:06 +0000
Subject: [PATCH 7/8] ensures that generic-cxx23 passes
---
libcxx/include/__vector/vector.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 2ffa67453adc9..46635045bc704 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -510,8 +510,8 @@ class vector {
template <_ContainerCompatibleRange<_Tp> _Range>
_LIBCPP_HIDE_FROM_ABI constexpr void append_range(_Range&& __range) {
if constexpr (ranges::forward_range<_Range> || ranges::sized_range<_Range>) {
- auto __len = static_cast<size_type>(ranges::distance(__range));
- if (__len < __raw_capacity() - __raw_sentinel()) {
+ auto __len = ranges::distance(__range);
+ if (__len < static_cast<difference_type>(__raw_capacity() - __raw_sentinel())) {
__construct_at_end(ranges::begin(__range), ranges::end(__range), __len);
} else {
__split_buffer __buffer(__recommend(size() + __len), size(), __alloc_);
>From fe98721a13c700986159e12a90a20134daf671b9 Mon Sep 17 00:00:00 2001
From: Christopher Di Bella <cjdb at google.com>
Date: Thu, 15 Jan 2026 02:23:38 +0000
Subject: [PATCH 8/8] attempts to fix GCC issue
---
libcxx/include/__vector/vector.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 46635045bc704..18004abbd1899 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -86,6 +86,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Allocator /* = allocator<_Tp> */>
class vector {
+#ifdef _LIBCPP_ABI_SIZE_BASED_VECTOR
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
+#else
+ using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
+#endif
public:
///
/// Types
@@ -605,7 +610,6 @@ class vector {
private:
using __sentinel_type _LIBCPP_NODEBUG = size_type;
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_size_layout>;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __raw_sentinel() const _NOEXCEPT {
return __size_;
@@ -656,7 +660,6 @@ class vector {
#else
private:
- using __split_buffer _LIBCPP_NODEBUG = __split_buffer<_Tp, _Allocator, __split_buffer_pointer_layout>;
using __sentinel_type _LIBCPP_NODEBUG = pointer;
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __raw_sentinel() const _NOEXCEPT {
More information about the libcxx-commits
mailing list