diff --git a/stl/inc/vector b/stl/inc/vector index 8286166d3d2..cb4b30bf69d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1,3747 +1,3747 @@ -// vector standard header - -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#ifndef _VECTOR_ -#define _VECTOR_ -#include -#if _STL_COMPILER_PREPROCESSOR -#include <__msvc_bit_utils.hpp> -#include <__msvc_sanitizer_annotate_container.hpp> -#include - -#if _HAS_CXX17 -#include -#endif // _HAS_CXX17 - -#pragma pack(push, _CRT_PACKING) -#pragma warning(push, _STL_WARNING_LEVEL) -#pragma warning(disable : _STL_DISABLED_WARNINGS) -_STL_DISABLE_CLANG_WARNINGS -#pragma push_macro("new") -#undef new - -_STD_BEGIN -template -class _Vector_const_iterator : public _Iterator_base { -public: -#ifdef __cpp_lib_concepts - using iterator_concept = contiguous_iterator_tag; -#endif // defined(__cpp_lib_concepts) - using iterator_category = random_access_iterator_tag; - using value_type = typename _Myvec::value_type; - using difference_type = typename _Myvec::difference_type; - using pointer = typename _Myvec::const_pointer; - using reference = const value_type&; - - using _Tptr = typename _Myvec::pointer; - - _CONSTEXPR20 _Vector_const_iterator() noexcept : _Ptr() {} - - _CONSTEXPR20 _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { - this->_Adopt(_Pvector); - } - - _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return *_Ptr; - } - - _NODISCARD _CONSTEXPR20 pointer operator->() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return _Ptr; - } - - _CONSTEXPR20 _Vector_const_iterator& operator++() noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); - _STL_VERIFY(_Mycont, "can't increment invalidated vector iterator"); - _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - ++_Ptr; - return *this; - } - - _CONSTEXPR20 _Vector_const_iterator operator++(int) noexcept { - _Vector_const_iterator _Tmp = *this; - ++*this; - return _Tmp; - } - - _CONSTEXPR20 _Vector_const_iterator& operator--() noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); - _STL_VERIFY(_Mycont, "can't decrement invalidated vector iterator"); - _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - --_Ptr; - return *this; - } - - _CONSTEXPR20 _Vector_const_iterator operator--(int) noexcept { - _Vector_const_iterator _Tmp = *this; - --*this; - return _Tmp; - } - - _CONSTEXPR20 void _Verify_offset(const difference_type _Off) const noexcept { -#if _ITERATOR_DEBUG_LEVEL == 0 - (void) _Off; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); - _STL_VERIFY(_Off == 0 || _Mycont, "cannot seek invalidated vector iterator"); - if (_Off < 0) { - _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); - } - - if (_Off > 0) { - _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); - } -#endif // _ITERATOR_DEBUG_LEVEL == 0 - } - - _CONSTEXPR20 _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { - _Verify_offset(_Off); - _Ptr += _Off; - return *this; - } - - _NODISCARD _CONSTEXPR20 _Vector_const_iterator operator+(const difference_type _Off) const noexcept { - _Vector_const_iterator _Tmp = *this; - _Tmp += _Off; - return _Tmp; - } - - _NODISCARD_FRIEND _CONSTEXPR20 _Vector_const_iterator operator+( - const difference_type _Off, _Vector_const_iterator _Next) noexcept { - _Next += _Off; - return _Next; - } - - _CONSTEXPR20 _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { - return *this += -_Off; - } - - _NODISCARD _CONSTEXPR20 _Vector_const_iterator operator-(const difference_type _Off) const noexcept { - _Vector_const_iterator _Tmp = *this; - _Tmp -= _Off; - return _Tmp; - } - - _NODISCARD _CONSTEXPR20 difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { - _Compat(_Right); - return _Ptr - _Right._Ptr; - } - - _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { - return *(*this + _Off); - } - - _NODISCARD _CONSTEXPR20 bool operator==(const _Vector_const_iterator& _Right) const noexcept { - _Compat(_Right); - return _Ptr == _Right._Ptr; - } - -#if _HAS_CXX20 - _NODISCARD constexpr strong_ordering operator<=>(const _Vector_const_iterator& _Right) const noexcept { - _Compat(_Right); - return _Unfancy(_Ptr) <=> _Unfancy(_Right._Ptr); - } -#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv - _NODISCARD bool operator!=(const _Vector_const_iterator& _Right) const noexcept { - return !(*this == _Right); - } - - _NODISCARD bool operator<(const _Vector_const_iterator& _Right) const noexcept { - _Compat(_Right); - return _Ptr < _Right._Ptr; - } - - _NODISCARD bool operator>(const _Vector_const_iterator& _Right) const noexcept { - return _Right < *this; - } - - _NODISCARD bool operator<=(const _Vector_const_iterator& _Right) const noexcept { - return !(_Right < *this); - } - - _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { - return !(*this < _Right); - } -#endif // !_HAS_CXX20 - - _CONSTEXPR20 void _Compat(const _Vector_const_iterator& _Right) const noexcept { - // test for compatible iterator pair -#if _ITERATOR_DEBUG_LEVEL == 0 - (void) _Right; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); -#endif // _ITERATOR_DEBUG_LEVEL == 0 - } - -#if _ITERATOR_DEBUG_LEVEL != 0 - friend _CONSTEXPR20 void _Verify_range( - const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { - _STL_VERIFY(_First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); - _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - using _Prevent_inheriting_unwrap = _Vector_const_iterator; - - _NODISCARD _CONSTEXPR20 const value_type* _Unwrapped() const noexcept { - return _Unfancy(_Ptr); - } - - _CONSTEXPR20 void _Seek_to(const value_type* _It) noexcept { - _Ptr = _Refancy<_Tptr>(const_cast(_It)); - } - - _Tptr _Ptr; // pointer to element in vector -}; - -#if _HAS_CXX20 -template -struct pointer_traits<_Vector_const_iterator<_Myvec>> { - using pointer = _Vector_const_iterator<_Myvec>; - using element_type = const typename pointer::value_type; // TRANSITION, VSO-1854115, omit typename - using difference_type = pointer::difference_type; - - _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - // A value-initialized iterator is in the domain of to_address. An invalidated end iterator for a vector with - // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose - // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an - // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return _STD to_address(_Iter._Ptr); - } -}; -#endif // _HAS_CXX20 - -template -class _Vector_iterator : public _Vector_const_iterator<_Myvec> { -public: - using _Mybase = _Vector_const_iterator<_Myvec>; - -#ifdef __cpp_lib_concepts - using iterator_concept = contiguous_iterator_tag; -#endif // defined(__cpp_lib_concepts) - using iterator_category = random_access_iterator_tag; - using value_type = typename _Myvec::value_type; - using difference_type = typename _Myvec::difference_type; - using pointer = typename _Myvec::pointer; - using reference = value_type&; - - using _Mybase::_Mybase; - - _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { - return const_cast(_Mybase::operator*()); - } - - _NODISCARD _CONSTEXPR20 pointer operator->() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); - _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); - _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, - "can't dereference out of range vector iterator"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return this->_Ptr; - } - - _CONSTEXPR20 _Vector_iterator& operator++() noexcept { - _Mybase::operator++(); - return *this; - } - - _CONSTEXPR20 _Vector_iterator operator++(int) noexcept { - _Vector_iterator _Tmp = *this; - _Mybase::operator++(); - return _Tmp; - } - - _CONSTEXPR20 _Vector_iterator& operator--() noexcept { - _Mybase::operator--(); - return *this; - } - - _CONSTEXPR20 _Vector_iterator operator--(int) noexcept { - _Vector_iterator _Tmp = *this; - _Mybase::operator--(); - return _Tmp; - } - - _CONSTEXPR20 _Vector_iterator& operator+=(const difference_type _Off) noexcept { - _Mybase::operator+=(_Off); - return *this; - } - - _NODISCARD _CONSTEXPR20 _Vector_iterator operator+(const difference_type _Off) const noexcept { - _Vector_iterator _Tmp = *this; - _Tmp += _Off; - return _Tmp; - } - - _NODISCARD_FRIEND _CONSTEXPR20 _Vector_iterator operator+( - const difference_type _Off, _Vector_iterator _Next) noexcept { - _Next += _Off; - return _Next; - } - - _CONSTEXPR20 _Vector_iterator& operator-=(const difference_type _Off) noexcept { - _Mybase::operator-=(_Off); - return *this; - } - - using _Mybase::operator-; - - _NODISCARD _CONSTEXPR20 _Vector_iterator operator-(const difference_type _Off) const noexcept { - _Vector_iterator _Tmp = *this; - _Tmp -= _Off; - return _Tmp; - } - - _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { - return const_cast(_Mybase::operator[](_Off)); - } - - using _Prevent_inheriting_unwrap = _Vector_iterator; - - _NODISCARD _CONSTEXPR20 value_type* _Unwrapped() const noexcept { - return _Unfancy(this->_Ptr); - } -}; - -#if _HAS_CXX20 -template -struct pointer_traits<_Vector_iterator<_Myvec>> { - using pointer = _Vector_iterator<_Myvec>; - using element_type = pointer::value_type; - using difference_type = pointer::difference_type; - - _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - // A value-initialized iterator is in the domain of to_address. An invalidated end iterator for a vector with - // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose - // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an - // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return _STD to_address(_Iter._Ptr); - } -}; -#endif // _HAS_CXX20 - -template -struct _Vec_iter_types { - using value_type = _Value_type; - using size_type = _Size_type; - using difference_type = _Difference_type; - using pointer = _Pointer; - using const_pointer = _Const_pointer; -}; - -struct _Value_init_tag { // tag to request value-initialization - explicit _Value_init_tag() = default; -}; - -template -class _Vector_val : public _Container_base { -public: - using value_type = typename _Val_types::value_type; - using size_type = typename _Val_types::size_type; - using difference_type = typename _Val_types::difference_type; - using pointer = typename _Val_types::pointer; - using const_pointer = typename _Val_types::const_pointer; - using reference = value_type&; - using const_reference = const value_type&; - - _CONSTEXPR20 _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} - - _CONSTEXPR20 _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept - : _Myfirst(_First), _Mylast(_Last), _Myend(_End) {} - - _CONSTEXPR20 void _Swap_val(_Vector_val& _Right) noexcept { - this->_Swap_proxy_and_iterators(_Right); - swap(_Myfirst, _Right._Myfirst); // intentional ADL - swap(_Mylast, _Right._Mylast); // intentional ADL - swap(_Myend, _Right._Myend); // intentional ADL - } - - _CONSTEXPR20 void _Take_contents(_Vector_val& _Right) noexcept { - this->_Swap_proxy_and_iterators(_Right); - _Myfirst = _Right._Myfirst; - _Mylast = _Right._Mylast; - _Myend = _Right._Myend; - - _Right._Myfirst = nullptr; - _Right._Mylast = nullptr; - _Right._Myend = nullptr; - } - - pointer _Myfirst; // pointer to beginning of array - pointer _Mylast; // pointer to current end of sequence - pointer _Myend; // pointer to end of array -}; - -template -constexpr auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { - // converts from a (potentially null) fancy pointer to a plain pointer - return _Ptr ? _STD addressof(*_Ptr) : nullptr; -} - -template -constexpr _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers - return _Ptr; -} - -_EXPORT_STD template > -class vector { // varying size array of values -private: - template - friend class _Vb_val; - friend _Tidy_guard; - - using _Alty = _Rebind_alloc_t<_Alloc, _Ty>; - using _Alty_traits = allocator_traits<_Alty>; - -public: - static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Ty, typename _Alloc::value_type>, - _MISMATCHED_ALLOCATOR_MESSAGE("vector", "T")); - static_assert(is_object_v<_Ty>, "The C++ Standard forbids containers of non-object types " - "because of [container.requirements]."); - - using value_type = _Ty; - using allocator_type = _Alloc; - using pointer = typename _Alty_traits::pointer; - using const_pointer = typename _Alty_traits::const_pointer; - using reference = _Ty&; - using const_reference = const _Ty&; - using size_type = typename _Alty_traits::size_type; - using difference_type = typename _Alty_traits::difference_type; - -private: -#ifdef _INSERT_VECTOR_ANNOTATION - _CONSTEXPR20 void _Create_annotation() const noexcept { - // Annotates the shadow memory of the valid range - auto& _My_data = _Mypair._Myval2; - _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Myend, _My_data._Mylast); - } - - _CONSTEXPR20 void _Remove_annotation() const noexcept { - // Removes the shadow memory annotation of the range - auto& _My_data = _Mypair._Myval2; - _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Myend); - } - - _CONSTEXPR20 void _Modify_annotation(const difference_type _Count) const noexcept { - // Extends/shrinks the annotated range by _Count - if (_Count == 0) { // nothing to do - // This also avoids calling _Apply_annotation() with null pointers - // when the vector has zero capacity, see GH-2464. - return; - } - - auto& _My_data = _Mypair._Myval2; - _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Mylast + _Count); - } - - static _CONSTEXPR20 void _Apply_annotation( - pointer _First_, pointer _End_, pointer _Old_last_, pointer _New_last_) noexcept { - _STL_INTERNAL_CHECK(_First_ != nullptr); - _STL_INTERNAL_CHECK(_End_ != nullptr); - _STL_INTERNAL_CHECK(_Old_last_ != nullptr); - _STL_INTERNAL_CHECK(_New_last_ != nullptr); - -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - return; - } -#endif // _HAS_CXX20 - - if (!_Asan_vector_should_annotate) { - return; - } - - const void* const _First = _STD _Unfancy(_First_); - const void* const _End = _STD _Unfancy(_End_); - const void* const _Old_last = _STD _Unfancy(_Old_last_); - const void* const _New_last = _STD _Unfancy(_New_last_); - if constexpr ((_Container_allocation_minimum_asan_alignment) >= _Asan_granularity) { - // old state: - // [_First, _Old_last) valid - // [_Old_last, _End) poison - // new state: - // [_First, _New_last) valid - // [_New_last, asan_aligned_after(_End)) poison - _CSTD __sanitizer_annotate_contiguous_container( - _First, _STD _Get_asan_aligned_after(_End), _Old_last, _New_last); - } else { - const auto _Aligned = _STD _Get_asan_aligned_first_end(_First, _End); - if (_Aligned._First == _Aligned._End) { - // The buffer does not end at least one shadow memory section; nothing to do. - return; - } - - const void* const _Old_fixed = _Aligned._Clamp_to_end(_Old_last); - const void* const _New_fixed = _Aligned._Clamp_to_end(_New_last); - - // old state: - // [_Aligned._First, _Old_fixed) valid - // [_Old_fixed, _Aligned._End) poison - // [_Aligned._End, _End) valid - // new state: - // [_Aligned._First, _New_fixed) valid - // [_New_fixed, _Aligned._End) poison - // [_Aligned._End, _End) valid - _CSTD __sanitizer_annotate_contiguous_container(_Aligned._First, _Aligned._End, _Old_fixed, _New_fixed); - } - } - - class _NODISCARD _Asan_extend_guard { - public: - _Asan_extend_guard(const _Asan_extend_guard&) = delete; - _Asan_extend_guard& operator=(const _Asan_extend_guard&) = delete; - - constexpr explicit _Asan_extend_guard(vector* _Myvec_, size_type _Target_size_) noexcept - : _Myvec(_Myvec_), _Target_size(_Target_size_) { - _STL_INTERNAL_CHECK(_Myvec != nullptr); - auto& _My_data = _Myvec->_Mypair._Myval2; - _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Myfirst + _Target_size); - } - - _CONSTEXPR20 ~_Asan_extend_guard() { - if (!_Myvec) { // Operation succeeded, no modification to the shadow memory required. - return; - } - - // Shrinks the shadow memory to the current size of the vector. - auto& _My_data = _Myvec->_Mypair._Myval2; - _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Myfirst + _Target_size, _My_data._Mylast); - } - - _CONSTEXPR20 void _Release() noexcept { - _Myvec = nullptr; - } - - private: - vector* _Myvec; - size_type _Target_size; - }; - - class _NODISCARD _Asan_create_guard { - public: - _Asan_create_guard(const _Asan_create_guard&) = delete; - _Asan_create_guard& operator=(const _Asan_create_guard&) = delete; - - constexpr explicit _Asan_create_guard(const vector& _Myvec_) noexcept : _Myvec(_Myvec_) {} - - _CONSTEXPR20 ~_Asan_create_guard() { - _Myvec._Create_annotation(); - } - - private: - const vector& _Myvec; - }; - -#define _ASAN_VECTOR_MODIFY(n) _Modify_annotation((n)) -#define _ASAN_VECTOR_REMOVE _Remove_annotation() -#define _ASAN_VECTOR_CREATE _Create_annotation() -#define _ASAN_VECTOR_CREATE_GUARD _Asan_create_guard _Annotator(*this) -#define _ASAN_VECTOR_EXTEND_GUARD(n) _Asan_extend_guard _Annotator(this, (n)) -#define _ASAN_VECTOR_RELEASE_GUARD _Annotator._Release() -#else // ^^^ _INSERT_VECTOR_ANNOTATION / !_INSERT_VECTOR_ANNOTATION vvv -#define _ASAN_VECTOR_MODIFY(n) -#define _ASAN_VECTOR_REMOVE -#define _ASAN_VECTOR_CREATE -#define _ASAN_VECTOR_CREATE_GUARD -#define _ASAN_VECTOR_EXTEND_GUARD(n) -#define _ASAN_VECTOR_RELEASE_GUARD -#endif // !_INSERT_VECTOR_ANNOTATION - - using _Scary_val = _Vector_val, _Simple_types<_Ty>, - _Vec_iter_types<_Ty, size_type, difference_type, pointer, const_pointer>>>; - -public: - using iterator = _Vector_iterator<_Scary_val>; - using const_iterator = _Vector_const_iterator<_Scary_val>; - using reverse_iterator = _STD reverse_iterator; - using const_reverse_iterator = _STD reverse_iterator; - - _CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Alty>) : _Mypair(_Zero_then_variadic_args_t{}) { - _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); - } - - _CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); - } - - _CONSTEXPR20 explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Construct_n(_Count); - } - - _CONSTEXPR20 vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Construct_n(_Count, _Val); - } - - template , int> = 0> - _CONSTEXPR20 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Adl_verify_range(_First, _Last); - auto _UFirst = _Get_unwrapped(_First); - auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { - const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); -#ifdef __cpp_lib_concepts - } else if constexpr (forward_iterator<_Iter>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); -#endif // defined(__cpp_lib_concepts) - } else { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); - _Tidy_guard _Guard{this}; - - _Append_uncounted_range(_STD move(_UFirst), _STD move(_ULast)); - - _Guard._Target = nullptr; - _Proxy._Release(); - } - } - - _CONSTEXPR20 vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Construct_n(_Convert_size(_Ilist.size()), _Ilist.begin(), _Ilist.end()); - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - constexpr vector(from_range_t, _Rng&& _Range, const _Alloc& _Al = _Alloc()) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - if constexpr (_RANGES sized_range<_Rng> || _RANGES forward_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Construct_n(_Count, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } else { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); - _Tidy_guard _Guard{this}; - - _Append_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - - _Guard._Target = nullptr; - _Proxy._Release(); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 vector(const vector& _Right) - : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { - const auto& _Right_data = _Right._Mypair._Myval2; - const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); - _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); - } - - _CONSTEXPR20 vector(const vector& _Right, const _Identity_t<_Alloc>& _Al) - : _Mypair(_One_then_variadic_args_t{}, _Al) { - const auto& _Right_data = _Right._Mypair._Myval2; - const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); - _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); - } - - _CONSTEXPR20 vector(vector&& _Right) noexcept - : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), - _STD exchange(_Right._Mypair._Myval2._Myfirst, nullptr), - _STD exchange(_Right._Mypair._Myval2._Mylast, nullptr), - _STD exchange(_Right._Mypair._Myval2._Myend, nullptr)) { - _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); - _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); - } - - _CONSTEXPR20 vector(vector&& _Right, const _Identity_t<_Alloc>& _Al_) noexcept( - _Alty_traits::is_always_equal::value) // strengthened - : _Mypair(_One_then_variadic_args_t{}, _Al_) { - _Alty& _Al = _Getal(); - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al); - auto& _My_data = _Mypair._Myval2; - auto& _Right_data = _Right._Mypair._Myval2; - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); - - if constexpr (!_Alty_traits::is_always_equal::value) { - if (_Al != _Right._Getal()) { - const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); - if (_Count != 0) { - _Buy_raw(_Count); - _Tidy_guard _Guard{this}; - _My_data._Mylast = - _Uninitialized_move(_Right_data._Myfirst, _Right_data._Mylast, _My_data._Myfirst, _Al); - - _ASAN_VECTOR_CREATE; - _Guard._Target = nullptr; - } - _Proxy._Release(); - return; - } - } - - _My_data._Take_contents(_Right_data); - _Proxy._Release(); - } - - _CONSTEXPR20 vector& operator=(vector&& _Right) noexcept( - _Choose_pocma_v<_Alty> != _Pocma_values::_No_propagate_allocators) { - if (this == _STD addressof(_Right)) { - return *this; - } - - _Alty& _Al = _Getal(); - _Alty& _Right_al = _Right._Getal(); - constexpr auto _Pocma_val = _Choose_pocma_v<_Alty>; - if constexpr (_Pocma_val == _Pocma_values::_No_propagate_allocators) { - if (_Al != _Right_al) { - _Move_assign_unequal_alloc(_Right); - return *this; - } - } - - _Tidy(); -#if _ITERATOR_DEBUG_LEVEL != 0 - if constexpr (_Pocma_val == _Pocma_values::_Propagate_allocators) { - if (_Al != _Right_al) { - // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 - _Mypair._Myval2._Reload_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al), _GET_PROXY_ALLOCATOR(_Alty, _Right_al)); - } - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - _Pocma(_Al, _Right_al); - _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); - return *this; - } - - _CONSTEXPR20 ~vector() noexcept { - _Tidy(); -#if _ITERATOR_DEBUG_LEVEL != 0 - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Delete_plain_internal(_Alproxy, _STD exchange(_Mypair._Myval2._Myproxy, nullptr)); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - } - -private: - template - _CONSTEXPR20 _Ty& _Emplace_one_at_back(_Valty&&... _Val) { - // insert by perfectly forwarding into element at end, provide strong guarantee - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - - if (_Mylast != _My_data._Myend) { - return _Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...); - } - - return *_Emplace_reallocate(_Mylast, _STD forward<_Valty>(_Val)...); - } - - template - _CONSTEXPR20 _Ty& _Emplace_back_with_unused_capacity(_Valty&&... _Val) { - // insert by perfectly forwarding into element at end, provide strong guarantee - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - _STL_INTERNAL_CHECK(_Mylast != _My_data._Myend); // check that we have unused capacity - if constexpr (conjunction_v, - _Uses_default_construct<_Alloc, _Ty*, _Valty...>>) { - _ASAN_VECTOR_MODIFY(1); - _Construct_in_place(*_Mylast, _STD forward<_Valty>(_Val)...); - } else { - _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Mylast - _My_data._Myfirst) + 1); - _Alty_traits::construct(_Getal(), _Unfancy(_Mylast), _STD forward<_Valty>(_Val)...); - _ASAN_VECTOR_RELEASE_GUARD; - } - - _Orphan_range(_Mylast, _Mylast); - _Ty& _Result = *_Mylast; - ++_Mylast; - - return _Result; - } - - template - _CONSTEXPR20 pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { - // reallocate and insert by perfectly forwarding _Val at _Whereptr - _Alty& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - _STL_INTERNAL_CHECK(_Mylast == _My_data._Myend); // check that we have no unused capacity - - const auto _Whereoff = static_cast(_Whereptr - _Myfirst); - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - - if (_Oldsize == max_size()) { - _Xlength(); - } - - const size_type _Newsize = _Oldsize + 1; - size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - const pointer _Constructed_last = _Newvec + _Whereoff + 1; - pointer _Constructed_first = _Constructed_last; - - _TRY_BEGIN - _Alty_traits::construct(_Al, _Unfancy(_Newvec + _Whereoff), _STD forward<_Valty>(_Val)...); - _Constructed_first = _Newvec + _Whereoff; - - if (_Whereptr == _Mylast) { // at back, provide strong guarantee - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); - } - } else { // provide basic guarantee - _Uninitialized_move(_Myfirst, _Whereptr, _Newvec, _Al); - _Constructed_first = _Newvec; - _Uninitialized_move(_Whereptr, _Mylast, _Newvec + _Whereoff + 1, _Al); - } - _CATCH_ALL - _Destroy_range(_Constructed_first, _Constructed_last, _Al); - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Newsize, _Newcapacity); - return _Newvec + _Whereoff; - } - -public: - template - _CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) { - // insert by perfectly forwarding into element at end, provide strong guarantee - _Ty& _Result = _Emplace_one_at_back(_STD forward<_Valty>(_Val)...); -#if _HAS_CXX17 - return _Result; -#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv - (void) _Result; -#endif // _HAS_CXX17 - } - - _CONSTEXPR20 void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee - _Emplace_one_at_back(_Val); - } - - _CONSTEXPR20 void push_back(_Ty&& _Val) { - // insert by moving into element at end, provide strong guarantee - _Emplace_one_at_back(_STD move(_Val)); - } - -private: - template - _CONSTEXPR20 void _Append_uncounted_range(_Iter _First, const _Sent _Last) { - // insert range [_First, _Last) at end - - // For one-at-back, provide strong guarantee. - // Otherwise, provide basic guarantee (despite N4950 [vector.modifiers]/2). - // Performance note: except for one-at-back, _Emplace_one_at_back()'s strong guarantee is unnecessary here. - - for (; _First != _Last; ++_First) { - _Emplace_one_at_back(*_First); - } - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template - _CONSTEXPR20 void _Append_counted_range(_Iter _First, const size_type _Count) { - // insert counted range _First + [0, _Count) at end - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - - const pointer _Oldfirst = _My_data._Myfirst; - const pointer _Oldlast = _Mylast; - const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); - - if (_Count == 0) { // nothing to do, avoid invalidating iterators - } else if (_Count > _Unused_capacity) { // reallocate - const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); - - if (_Count > max_size() - _Oldsize) { - _Xlength(); - } - - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - const pointer _Constructed_last = _Newvec + _Oldsize + _Count; - pointer _Constructed_first = _Constructed_last; - - _TRY_BEGIN - _Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Oldsize, _Al); - _Constructed_first = _Newvec + _Oldsize; - - if (_Count == 1) { // one at back, provide strong guarantee - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); - } - } else { // provide basic guarantee - _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); - } - _CATCH_ALL - _Destroy_range(_Constructed_first, _Constructed_last, _Al); - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Newsize, _Newcapacity); - } else { // Provide the strong guarantee. - // Performance note: except for one-at-back, the strong guarantee is unnecessary here. - - _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _Oldfirst) + _Count); - _Mylast = _Uninitialized_copy_n(_STD move(_First), _Count, _Oldlast, _Al); - _ASAN_VECTOR_RELEASE_GUARD; - - _Orphan_range(_Oldlast, _Oldlast); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - -public: -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - constexpr void append_range(_Rng&& _Range) { - if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Append_counted_range(_RANGES _Ubegin(_Range), _Count); - } else { - _Append_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - template - _CONSTEXPR20 iterator emplace(const_iterator _Where, _Valty&&... _Val) { - // insert by perfectly forwarding _Val at _Where - const pointer _Whereptr = _Where._Ptr; - auto& _My_data = _Mypair._Myval2; - const pointer _Oldlast = _My_data._Mylast; -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Oldlast >= _Whereptr, - "vector emplace iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Oldlast != _My_data._Myend) { - if (_Whereptr == _Oldlast) { // at back, provide strong guarantee - _Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...); - } else { - auto& _Al = _Getal(); - _Alloc_temporary2<_Alty> _Obj(_Al, _STD forward<_Valty>(_Val)...); // handle aliasing - // after constructing _Obj, provide basic guarantee - _Orphan_range(_Whereptr, _Oldlast); - _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _My_data._Myfirst) + 1); - _Alty_traits::construct(_Al, _Unfancy(_Oldlast), _STD move(_Oldlast[-1])); - _ASAN_VECTOR_RELEASE_GUARD; - ++_My_data._Mylast; - _Move_backward_unchecked(_Whereptr, _Oldlast - 1, _Oldlast); - *_Whereptr = _STD move(_Obj._Get_value()); - } - - return _Make_iterator(_Whereptr); - } - - return _Make_iterator(_Emplace_reallocate(_Whereptr, _STD forward<_Valty>(_Val)...)); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where - return emplace(_Where, _Val); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where - return emplace(_Where, _STD move(_Val)); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { - // insert _Count * _Val at _Where - const pointer _Whereptr = _Where._Ptr; - - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - - const pointer _Oldfirst = _My_data._Myfirst; - const pointer _Oldlast = _Mylast; -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, - "vector insert iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); - const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); - const bool _One_at_back = _Count == 1 && _Whereptr == _Oldlast; - if (_Count == 0) { // nothing to do, avoid invalidating iterators - } else if (_Count > _Unused_capacity) { // reallocate - const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); - - if (_Count > max_size() - _Oldsize) { - _Xlength(); - } - - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - const pointer _Constructed_last = _Newvec + _Whereoff + _Count; - pointer _Constructed_first = _Constructed_last; - - _TRY_BEGIN - _Uninitialized_fill_n(_Newvec + _Whereoff, _Count, _Val, _Al); - _Constructed_first = _Newvec + _Whereoff; - - if (_One_at_back) { // provide strong guarantee - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); - } - } else { // provide basic guarantee - _Uninitialized_move(_Oldfirst, _Whereptr, _Newvec, _Al); - _Constructed_first = _Newvec; - _Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al); - } - _CATCH_ALL - _Destroy_range(_Constructed_first, _Constructed_last, _Al); - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Newsize, _Newcapacity); - } else if (_One_at_back) { // provide strong guarantee - _Emplace_back_with_unused_capacity(_Val); - } else { // provide basic guarantee - const _Alloc_temporary2<_Alty> _Tmp_storage(_Al, _Val); // handle aliasing - const auto& _Tmp = _Tmp_storage._Get_value(); - const auto _Affected_elements = static_cast(_Oldlast - _Whereptr); - _Orphan_range(_Whereptr, _Oldlast); - - _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _My_data._Myfirst) + _Count); - if (_Count > _Affected_elements) { // new stuff spills off end - _Mylast = _Uninitialized_fill_n(_Oldlast, _Count - _Affected_elements, _Tmp, _Al); - _Mylast = _Uninitialized_move(_Whereptr, _Oldlast, _Mylast, _Al); - _STD fill(_Whereptr, _Oldlast, _Tmp); - } else { // new stuff can all be assigned - _Mylast = _Uninitialized_move(_Oldlast - _Count, _Oldlast, _Oldlast, _Al); - _Move_backward_unchecked(_Whereptr, _Oldlast - _Count, _Oldlast); - _STD fill_n(_Whereptr, _Count, _Tmp); - } - _ASAN_VECTOR_RELEASE_GUARD; - } - - return _Make_iterator_offset(_Whereoff); - } - -private: - template - _CONSTEXPR20 void _Insert_uncounted_range(const_iterator _Where, _Iter _First, _Sent _Last) { - // insert range [_First, _Last) at _Where - if (_First == _Last) { - return; // nothing to do, avoid invalidating iterators - } - - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - const auto _Whereoff = static_cast(_Where._Ptr - _Myfirst); - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - - _Append_uncounted_range(_STD move(_First), _STD move(_Last)); - - _Orphan_range(_Myfirst + _Whereoff, _Myfirst + _Oldsize); - - _STD rotate(_Myfirst + _Whereoff, _Myfirst + _Oldsize, _Mylast); - } - - template - _CONSTEXPR20 void _Insert_counted_range(const_iterator _Where, _Iter _First, const size_type _Count) { - // insert counted range _First + [0, _Count) at _Where - const pointer _Whereptr = _Where._Ptr; - - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - - const pointer _Oldfirst = _My_data._Myfirst; - const pointer _Oldlast = _Mylast; - const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); - - if (_Count == 0) { // nothing to do, avoid invalidating iterators - } else if (_Count > _Unused_capacity) { // reallocate - const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); - - if (_Count > max_size() - _Oldsize) { - _Xlength(); - } - - const size_type _Newsize = _Oldsize + _Count; - size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); - const pointer _Constructed_last = _Newvec + _Whereoff + _Count; - pointer _Constructed_first = _Constructed_last; - - _TRY_BEGIN - _Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Whereoff, _Al); - _Constructed_first = _Newvec + _Whereoff; - - if (_Count == 1 && _Whereptr == _Oldlast) { // one at back, provide strong guarantee - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); - } - } else { // provide basic guarantee - _Uninitialized_move(_Oldfirst, _Whereptr, _Newvec, _Al); - _Constructed_first = _Newvec; - _Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al); - } - _CATCH_ALL - _Destroy_range(_Constructed_first, _Constructed_last, _Al); - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Newsize, _Newcapacity); - } else { // Attempt to provide the strong guarantee for EmplaceConstructible failure. - // If we encounter copy/move construction/assignment failure, provide the basic guarantee. - // (For one-at-back, this provides the strong guarantee.) - - const auto _Affected_elements = static_cast(_Oldlast - _Whereptr); - - _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _Oldfirst) + _Count); - if (_Count < _Affected_elements) { // some affected elements must be assigned - _Mylast = _Uninitialized_move(_Oldlast - _Count, _Oldlast, _Oldlast, _Al); - _Move_backward_unchecked(_Whereptr, _Oldlast - _Count, _Oldlast); - _Destroy_range(_Whereptr, _Whereptr + _Count, _Al); - - _TRY_BEGIN - _Uninitialized_copy_n(_STD move(_First), _Count, _Whereptr, _Al); - _CATCH_ALL - // glue the broken pieces back together - - _TRY_BEGIN - _Uninitialized_move(_Whereptr + _Count, _Whereptr + 2 * _Count, _Whereptr, _Al); - _CATCH_ALL - // vaporize the detached piece - _Orphan_range(_Whereptr, _Oldlast); - _Destroy_range(_Whereptr + _Count, _Mylast, _Al); - _Mylast = _Whereptr; - _RERAISE; - _CATCH_END - - _STD _Move_unchecked(_Whereptr + 2 * _Count, _Mylast, _Whereptr + _Count); - _Destroy_range(_Oldlast, _Mylast, _Al); - _Mylast = _Oldlast; - _RERAISE; - _CATCH_END - } else { // affected elements don't overlap before/after - const pointer _Relocated = _Whereptr + _Count; - _Mylast = _Uninitialized_move(_Whereptr, _Oldlast, _Relocated, _Al); - _Destroy_range(_Whereptr, _Oldlast, _Al); - - _TRY_BEGIN - _Uninitialized_copy_n(_STD move(_First), _Count, _Whereptr, _Al); - _CATCH_ALL - // glue the broken pieces back together - - _TRY_BEGIN - _Uninitialized_move(_Relocated, _Mylast, _Whereptr, _Al); - _CATCH_ALL - // vaporize the detached piece - _Orphan_range(_Whereptr, _Oldlast); - _Destroy_range(_Relocated, _Mylast, _Al); - _Mylast = _Whereptr; - _RERAISE; - _CATCH_END - - _Destroy_range(_Relocated, _Mylast, _Al); - _Mylast = _Oldlast; - _RERAISE; - _CATCH_END - } - - _Orphan_range(_Whereptr, _Oldlast); - _ASAN_VECTOR_RELEASE_GUARD; - } - } - -public: - template , int> = 0> - _CONSTEXPR20 iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { - const pointer _Whereptr = _Where._Ptr; - auto& _My_data = _Mypair._Myval2; - const pointer _Oldfirst = _My_data._Myfirst; -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, - "vector insert iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - _Adl_verify_range(_First, _Last); - auto _UFirst = _Get_unwrapped(_First); - auto _ULast = _Get_unwrapped(_Last); - const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); - if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { - const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Insert_counted_range(_Where, _UFirst, _Count); -#ifdef __cpp_lib_concepts - } else if constexpr (forward_iterator<_Iter>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Insert_counted_range(_Where, _UFirst, _Count); -#endif // defined(__cpp_lib_concepts) - } else { - _Insert_uncounted_range(_Where, _UFirst, _ULast); - } - return _Make_iterator_offset(_Whereoff); - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - constexpr iterator insert_range(const_iterator _Where, _Rng&& _Range) { - const pointer _Whereptr = _Where._Ptr; - auto& _My_data = _Mypair._Myval2; - const pointer _Oldfirst = _My_data._Myfirst; -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, - "vector insert_range iterator out-of-range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); - - if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Insert_counted_range(_Where, _RANGES _Ubegin(_Range), _Count); - } else { - _Insert_uncounted_range(_Where, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } - return _Make_iterator_offset(_Whereoff); - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { - const pointer _Whereptr = _Where._Ptr; - auto& _My_data = _Mypair._Myval2; - const pointer _Oldfirst = _My_data._Myfirst; -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, - "vector insert iterator out-of-range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); - - const auto _Count = _Convert_size(_Ilist.size()); - _Insert_counted_range(_Where, _Ilist.begin(), _Count); - return _Make_iterator_offset(_Whereoff); - } - - _CONSTEXPR20 void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { - // assign _Newsize * _Val - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - -#if _ITERATOR_DEBUG_LEVEL == 2 -#if _HAS_CXX20 - if (!_STD is_constant_evaluated()) -#endif // _HAS_CXX20 - { - const auto _Valptr = _STD addressof(_Val); - _STL_VERIFY(!(_Unfancy(_Myfirst) <= _Valptr && _Valptr < _Unfancy(_Mylast)), - "assignment value cannot be a reference into the container"); - } -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - constexpr bool _Nothrow_construct = - conjunction_v, _Uses_default_construct<_Alloc, _Ty*, const _Ty&>>; - - _My_data._Orphan_all(); - const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { // reallocate - _Clear_and_reserve_geometric(_Newsize); - if constexpr (_Nothrow_construct) { - _Mylast = _Uninitialized_fill_n(_Myfirst, _Newsize, _Val, _Al); - _ASAN_VECTOR_CREATE; - } else { - _ASAN_VECTOR_CREATE_GUARD; - _Mylast = _Uninitialized_fill_n(_Myfirst, _Newsize, _Val, _Al); - } - - return; - } - - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - if (_Newsize > _Oldsize) { - _STD fill(_Myfirst, _Mylast, _Val); - if constexpr (_Nothrow_construct) { - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Uninitialized_fill_n(_Mylast, _Newsize - _Oldsize, _Val, _Al); - } else { - _ASAN_VECTOR_EXTEND_GUARD(_Newsize); - _Mylast = _Uninitialized_fill_n(_Mylast, _Newsize - _Oldsize, _Val, _Al); - _ASAN_VECTOR_RELEASE_GUARD; - } - } else { - const pointer _Newlast = _Myfirst + _Newsize; - _STD fill(_Myfirst, _Newlast, _Val); - _Destroy_range(_Newlast, _Mylast, _Al); - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Newlast; - } - } - -private: - template - _CONSTEXPR20 void _Assign_uncounted_range(_Iter _First, _Sent _Last) { - // assign unknown number of elements from [_First, _Last) - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - _My_data._Orphan_all(); - - pointer _Next = _Myfirst; - for (; _First != _Last && _Next != _Mylast; ++_First, (void) ++_Next) { - *_Next = *_First; - } - - // Code size optimization: we've exhausted only the source, only the dest, or both. - // If we've exhausted only the source: we Trim, then Append does nothing. - // If we've exhausted only the dest: Trim does nothing, then we Append. - // If we've exhausted both: Trim does nothing, then Append does nothing. - - // Trim. - _Destroy_range(_Next, _Mylast, _Getal()); - _ASAN_VECTOR_MODIFY(static_cast(_Next - _Mylast)); // negative when destroying elements - _Mylast = _Next; - - _Append_uncounted_range(_STD move(_First), _STD move(_Last)); - } - - template - _CONSTEXPR20 void _Assign_counted_range(_Iter _First, const size_type _Newsize) { - // assign elements from counted range _First + [0, _Newsize) - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - - constexpr bool _Nothrow_construct = conjunction_v>, - _Uses_default_construct<_Alloc, _Ty*, _Iter_ref_t<_Iter>>>; - - _My_data._Orphan_all(); - const auto _Oldcapacity = static_cast(_Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { - _Clear_and_reserve_geometric(_Newsize); - if constexpr (_Nothrow_construct) { - _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize, _Myfirst, _Al); - _ASAN_VECTOR_CREATE; - } else { - _ASAN_VECTOR_CREATE_GUARD; - _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize, _Myfirst, _Al); - } - return; - } - - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - if (_Newsize > _Oldsize) { - bool _Copied = false; - if constexpr (_Iter_copy_cat<_Iter, pointer>::_Bitcopy_assignable) { -#if _HAS_CXX20 - if (!_STD is_constant_evaluated()) -#endif // _HAS_CXX20 - { - _Copy_memmove_n(_First, static_cast(_Oldsize), _Myfirst); - _First += _Oldsize; - _Copied = true; - } - } - - if (!_Copied) { - for (auto _Mid = _Myfirst; _Mid != _Mylast; ++_Mid, (void) ++_First) { - *_Mid = *_First; - } - } - - if constexpr (_Nothrow_construct) { - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize - _Oldsize, _Mylast, _Al); - } else { - _ASAN_VECTOR_EXTEND_GUARD(_Newsize); - _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize - _Oldsize, _Mylast, _Al); - _ASAN_VECTOR_RELEASE_GUARD; - } - } else { - const pointer _Newlast = _Myfirst + _Newsize; - _Copy_n_unchecked4(_STD move(_First), _Newsize, _Myfirst); - _Destroy_range(_Newlast, _Mylast, _Al); - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Newlast; - } - } - -public: - template , int> = 0> - _CONSTEXPR20 void assign(_Iter _First, _Iter _Last) { - _Adl_verify_range(_First, _Last); - auto _UFirst = _Get_unwrapped(_First); - auto _ULast = _Get_unwrapped(_Last); - if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { - const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Assign_counted_range(_UFirst, _Count); -#ifdef __cpp_lib_concepts - } else if constexpr (forward_iterator<_Iter>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - _Assign_counted_range(_UFirst, _Count); -#endif // defined(__cpp_lib_concepts) - } else { - _Assign_uncounted_range(_UFirst, _ULast); - } - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range<_Ty> _Rng> - constexpr void assign_range(_Rng&& _Range) { - if constexpr (_RANGES sized_range<_Rng> || _RANGES forward_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); - } else { - _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 void assign(const initializer_list<_Ty> _Ilist) { - const auto _Count = _Convert_size(_Ilist.size()); - _Assign_counted_range(_Ilist.begin(), _Count); - } - - _CONSTEXPR20 vector& operator=(const vector& _Right) { - if (this == _STD addressof(_Right)) { - return *this; - } - - auto& _Al = _Getal(); - auto& _Right_al = _Right._Getal(); - if constexpr (_Choose_pocca_v<_Alty>) { - if (_Al != _Right_al) { - _Tidy(); - _Mypair._Myval2._Reload_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al), _GET_PROXY_ALLOCATOR(_Alty, _Right_al)); - } - } - - _Pocca(_Al, _Right_al); - auto& _Right_data = _Right._Mypair._Myval2; - _Assign_counted_range(_Right_data._Myfirst, static_cast(_Right_data._Mylast - _Right_data._Myfirst)); - - return *this; - } - - _CONSTEXPR20 vector& operator=(initializer_list<_Ty> _Ilist) { - const auto _Count = _Convert_size(_Ilist.size()); - _Assign_counted_range(_Ilist.begin(), _Count); - return *this; - } - -private: - template - _CONSTEXPR20 void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { - if (_Newsize > max_size()) { - _Xlength(); - } - - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - size_type _Newcapacity = _Calculate_growth(_Newsize); - - const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - const pointer _Appended_first = _Newvec + _Oldsize; - pointer _Appended_last = _Appended_first; - - _TRY_BEGIN - if constexpr (is_same_v<_Ty2, _Ty>) { - _Appended_last = _Uninitialized_fill_n(_Appended_first, _Newsize - _Oldsize, _Val, _Al); - } else { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Ty2, _Value_init_tag>); - _Appended_last = _Uninitialized_value_construct_n(_Appended_first, _Newsize - _Oldsize, _Al); - } - - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); - } - _CATCH_ALL - _Destroy_range(_Appended_first, _Appended_last, _Al); - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Newsize, _Newcapacity); - } - - template - _CONSTEXPR20 void _Resize(const size_type _Newsize, const _Ty2& _Val) { - // trim or append elements, provide strong guarantee - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - if (_Newsize < _Oldsize) { // trim - const pointer _Newlast = _Myfirst + _Newsize; - _Orphan_range(_Newlast, _Mylast); - _Destroy_range(_Newlast, _Mylast, _Al); - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Newlast; - return; - } - - if (_Newsize > _Oldsize) { // append - const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { // reallocate - _Resize_reallocate(_Newsize, _Val); - return; - } - - _ASAN_VECTOR_EXTEND_GUARD(_Newsize); - const pointer _Oldlast = _Mylast; - if constexpr (is_same_v<_Ty2, _Ty>) { - _Mylast = _Uninitialized_fill_n(_Oldlast, _Newsize - _Oldsize, _Val, _Al); - } else { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Ty2, _Value_init_tag>); - _Mylast = _Uninitialized_value_construct_n(_Oldlast, _Newsize - _Oldsize, _Al); - } - _ASAN_VECTOR_RELEASE_GUARD; - _Orphan_range(_Oldlast, _Oldlast); - } - - // if _Newsize == _Oldsize, do nothing; avoid invalidating iterators - } - -public: - _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { - // trim or append value-initialized elements, provide strong guarantee - _Resize(_Newsize, _Value_init_tag{}); - } - - _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { - // trim or append copies of _Val, provide strong guarantee - _Resize(_Newsize, _Val); - } - -private: - enum class _Reallocation_policy { _At_least, _Exactly }; - - template <_Reallocation_policy _Policy> - _CONSTEXPR20 void _Reallocate(size_type& _Newcapacity) { - // set capacity to _Newcapacity (without geometric growth), provide strong guarantee - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - const auto _Size = static_cast(_Mylast - _Myfirst); - - pointer _Newvec; - if constexpr (_Policy == _Reallocation_policy::_At_least) { - _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); - } else { - _STL_INTERNAL_STATIC_ASSERT(_Policy == _Reallocation_policy::_Exactly); - _Newvec = _Al.allocate(_Newcapacity); - } - - _TRY_BEGIN - if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { - _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); - } else { - _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); - } - _CATCH_ALL - _Al.deallocate(_Newvec, _Newcapacity); - _RERAISE; - _CATCH_END - - _Change_array(_Newvec, _Size, _Newcapacity); - } - -#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) - void _Check_all_orphaned_locked() const noexcept { - _Lockit _Lock(_LOCK_DEBUG); - auto& _My_data = _Mypair._Myval2; - _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); - } - - _CONSTEXPR20 void _Check_all_orphaned() const noexcept { -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - auto& _My_data = _Mypair._Myval2; - _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); - } else -#endif // _HAS_CXX20 - { - _Check_all_orphaned_locked(); - } - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) - - _CONSTEXPR20 void _Clear_and_reserve_geometric(const size_type _Newsize) { - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - -#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) - _STL_INTERNAL_CHECK(_Newsize != 0); - _Check_all_orphaned(); -#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) - - if (_Newsize > max_size()) { - _Xlength(); - } - - const size_type _Newcapacity = _Calculate_growth(_Newsize); - - if (_Myfirst) { // destroy and deallocate old array - _Destroy_range(_Myfirst, _Mylast, _Al); - _ASAN_VECTOR_REMOVE; - _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); - - _Myfirst = nullptr; - _Mylast = nullptr; - _Myend = nullptr; - } - - _Buy_raw(_Newcapacity); - } - -public: - _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW size_type _Newcapacity) { - // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee - if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks) - if (_Newcapacity > max_size()) { - _Xlength(); - } - - _Reallocate<_Reallocation_policy::_At_least>(_Newcapacity); - } - } - - _CONSTEXPR20 void shrink_to_fit() { // reduce capacity to size, provide strong guarantee - auto& _My_data = _Mypair._Myval2; - const pointer _Oldlast = _My_data._Mylast; - if (_Oldlast != _My_data._Myend) { // something to do - const pointer _Oldfirst = _My_data._Myfirst; - if (_Oldfirst == _Oldlast) { - _Tidy(); - } else { - size_type _Newcapacity = static_cast(_Oldlast - _Oldfirst); - _Reallocate<_Reallocation_policy::_Exactly>(_Newcapacity); - } - } - } - - _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - _Orphan_range(_Mylast - 1, _Mylast); - _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); - _ASAN_VECTOR_MODIFY(-1); - --_Mylast; - } - - _CONSTEXPR20 iterator erase(const_iterator _Where) noexcept( - is_nothrow_move_assignable_v) /* strengthened */ { - const pointer _Whereptr = _Where._Ptr; - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, - "vector erase iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - _Orphan_range(_Whereptr, _Mylast); - _STD _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); - _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); - _ASAN_VECTOR_MODIFY(-1); - --_Mylast; - return iterator(_Whereptr, _STD addressof(_My_data)); - } - - _CONSTEXPR20 iterator erase(const_iterator _First, const_iterator _Last) noexcept( - is_nothrow_move_assignable_v) /* strengthened */ { - const pointer _Firstptr = _First._Ptr; - const pointer _Lastptr = _Last._Ptr; - auto& _My_data = _Mypair._Myval2; - pointer& _Mylast = _My_data._Mylast; - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) - && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, - "vector erase iterator outside range"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Firstptr != _Lastptr) { // something to do, invalidate iterators - _Orphan_range(_Firstptr, _Mylast); - - const pointer _Newlast = _STD _Move_unchecked(_Lastptr, _Mylast, _Firstptr); - _Destroy_range(_Newlast, _Mylast, _Getal()); - _ASAN_VECTOR_MODIFY(static_cast(_Newlast - _Mylast)); // negative when destroying elements - _Mylast = _Newlast; - } - - return iterator(_Firstptr, _STD addressof(_My_data)); - } - - _CONSTEXPR20 void clear() noexcept { // erase all - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - if (_Myfirst == _Mylast) { // already empty, nothing to do - // This is an optimization for debug mode: we can avoid taking the debug lock to invalidate iterators. - // Note that when clearing an empty vector, this will preserve past-the-end iterators, which is allowed by - // N4950 [sequence.reqmts]/54 "a.clear() [...] may invalidate the past-the-end iterator". - return; - } - - _My_data._Orphan_all(); - _Destroy_range(_Myfirst, _Mylast, _Getal()); - _ASAN_VECTOR_MODIFY(static_cast(_Myfirst - _Mylast)); // negative when destroying elements - _Mylast = _Myfirst; - } - - _CONSTEXPR20 void swap(vector& _Right) noexcept /* strengthened */ { - if (this != _STD addressof(_Right)) { - _Pocs(_Getal(), _Right._Getal()); - _Mypair._Myval2._Swap_val(_Right._Mypair._Myval2); - } - } - - _NODISCARD _CONSTEXPR20 _Ty* data() noexcept { - return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); - } - - _NODISCARD _CONSTEXPR20 const _Ty* data() const noexcept { - return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); - } - - _NODISCARD _CONSTEXPR20 iterator begin() noexcept { - auto& _My_data = _Mypair._Myval2; - return iterator(_My_data._Myfirst, _STD addressof(_My_data)); - } - - _NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept { - auto& _My_data = _Mypair._Myval2; - return const_iterator(_My_data._Myfirst, _STD addressof(_My_data)); - } - - _NODISCARD _CONSTEXPR20 iterator end() noexcept { - auto& _My_data = _Mypair._Myval2; - return iterator(_My_data._Mylast, _STD addressof(_My_data)); - } - - _NODISCARD _CONSTEXPR20 const_iterator end() const noexcept { - auto& _My_data = _Mypair._Myval2; - return const_iterator(_My_data._Mylast, _STD addressof(_My_data)); - } - - _NODISCARD _CONSTEXPR20 reverse_iterator rbegin() noexcept { - return reverse_iterator(end()); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end()); - } - - _NODISCARD _CONSTEXPR20 reverse_iterator rend() noexcept { - return reverse_iterator(begin()); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin()); - } - - _NODISCARD _CONSTEXPR20 const_iterator cbegin() const noexcept { - return begin(); - } - - _NODISCARD _CONSTEXPR20 const_iterator cend() const noexcept { - return end(); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { - return rbegin(); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator crend() const noexcept { - return rend(); - } - - _NODISCARD _CONSTEXPR20 pointer _Unchecked_begin() noexcept { - return _Mypair._Myval2._Myfirst; - } - - _NODISCARD _CONSTEXPR20 const_pointer _Unchecked_begin() const noexcept { - return _Mypair._Myval2._Myfirst; - } - - _NODISCARD _CONSTEXPR20 pointer _Unchecked_end() noexcept { - return _Mypair._Myval2._Mylast; - } - - _NODISCARD _CONSTEXPR20 const_pointer _Unchecked_end() const noexcept { - return _Mypair._Myval2._Mylast; - } - - _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { - auto& _My_data = _Mypair._Myval2; - return _My_data._Myfirst == _My_data._Mylast; - } - - _NODISCARD _CONSTEXPR20 size_type size() const noexcept { - auto& _My_data = _Mypair._Myval2; - return static_cast(_My_data._Mylast - _My_data._Myfirst); - } - - _NODISCARD _CONSTEXPR20 size_type max_size() const noexcept { - return (_STD min)( - static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); - } - - _NODISCARD _CONSTEXPR20 size_type capacity() const noexcept { - auto& _My_data = _Mypair._Myval2; - return static_cast(_My_data._Myend - _My_data._Myfirst); - } - - _NODISCARD _CONSTEXPR20 _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return _My_data._Myfirst[_Pos]; - } - - _NODISCARD _CONSTEXPR20 const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return _My_data._Myfirst[_Pos]; - } - - _NODISCARD _CONSTEXPR20 _Ty& at(const size_type _Pos) { - auto& _My_data = _Mypair._Myval2; - if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { - _Xrange(); - } - - return _My_data._Myfirst[_Pos]; - } - - _NODISCARD _CONSTEXPR20 const _Ty& at(const size_type _Pos) const { - auto& _My_data = _Mypair._Myval2; - if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { - _Xrange(); - } - - return _My_data._Myfirst[_Pos]; - } - - _NODISCARD _CONSTEXPR20 _Ty& front() noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *_My_data._Myfirst; - } - - _NODISCARD _CONSTEXPR20 const _Ty& front() const noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *_My_data._Myfirst; - } - - _NODISCARD _CONSTEXPR20 _Ty& back() noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return _My_data._Mylast[-1]; - } - - _NODISCARD _CONSTEXPR20 const _Ty& back() const noexcept /* strengthened */ { - auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return _My_data._Mylast[-1]; - } - - _NODISCARD _CONSTEXPR20 allocator_type get_allocator() const noexcept { - return static_cast(_Getal()); - } - -private: - _CONSTEXPR20 size_type _Calculate_growth(const size_type _Newsize) const { - // given _Oldcapacity and _Newsize, calculate geometric growth - const size_type _Oldcapacity = capacity(); - const auto _Max = max_size(); - - if (_Oldcapacity > _Max - _Oldcapacity / 2) { - return _Max; // geometric growth would overflow - } - - const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2; - - if (_Geometric < _Newsize) { - return _Newsize; // geometric growth would be insufficient - } - - return _Geometric; // geometric growth is sufficient - } - - _CONSTEXPR20 void _Buy_raw(size_type _Newcapacity) { - // allocate array with _Newcapacity elements - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - - _STL_INTERNAL_CHECK(!_Myfirst && !_Mylast && !_Myend); // check that *this is tidy - _STL_INTERNAL_CHECK(0 < _Newcapacity && _Newcapacity <= max_size()); - - const pointer _Newvec = _Allocate_at_least_helper(_Getal(), _Newcapacity); - _Myfirst = _Newvec; - _Mylast = _Newvec; - _Myend = _Newvec + _Newcapacity; - } - - _CONSTEXPR20 void _Buy_nonzero(const size_type _Newcapacity) { - // allocate array with _Newcapacity elements -#ifdef _ENABLE_STL_INTERNAL_CHECK - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - _STL_INTERNAL_CHECK(!_Myfirst && !_Mylast && !_Myend); // check that *this is tidy - _STL_INTERNAL_CHECK(0 < _Newcapacity); -#endif // _ENABLE_STL_INTERNAL_CHECK - - if (_Newcapacity > max_size()) { - _Xlength(); - } - - _Buy_raw(_Newcapacity); - } - - _CONSTEXPR20 void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { - // orphan all iterators, discard old array, acquire new array - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - - _My_data._Orphan_all(); - - if (_Myfirst) { // destroy and deallocate old array - _Destroy_range(_Myfirst, _Mylast, _Al); - _ASAN_VECTOR_REMOVE; - _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); - } - - _Myfirst = _Newvec; - _Mylast = _Newvec + _Newsize; - _Myend = _Newvec + _Newcapacity; - _ASAN_VECTOR_CREATE; - } - - _CONSTEXPR20 void _Tidy() noexcept { // free all storage - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - pointer& _Myend = _My_data._Myend; - - _My_data._Orphan_all(); - - if (_Myfirst) { // destroy and deallocate old array - _Destroy_range(_Myfirst, _Mylast, _Al); - _ASAN_VECTOR_REMOVE; - _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); - - _Myfirst = nullptr; - _Mylast = nullptr; - _Myend = nullptr; - } - } - - template - _CONSTEXPR20 void _Construct_n(_CRT_GUARDOVERFLOW const size_type _Count, _Valty&&... _Val) { - // Dispatches between the three sized constructions. - // 1-arg -> value-construction, e.g. vector(5) - // 2-arg -> fill, e.g. vector(5, "meow") - // 3-arg -> sized range construction, e.g. vector{"Hello", "Fluffy", "World"} - auto& _Al = _Getal(); - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al); - auto& _My_data = _Mypair._Myval2; - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); - if (_Count != 0) { - _Buy_nonzero(_Count); - _Tidy_guard _Guard{this}; - if constexpr (sizeof...(_Val) == 0) { - _My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al); - } else if constexpr (sizeof...(_Val) == 1) { - _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Valty..., const _Ty&>); - _My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val..., _Al); - } else if constexpr (sizeof...(_Val) == 2) { - _My_data._Mylast = _Uninitialized_copy(_STD forward<_Valty>(_Val)..., _My_data._Myfirst, _Al); - } else { - static_assert(_Always_false<_Ty>, "Should be unreachable"); - } - _ASAN_VECTOR_CREATE; - _Guard._Target = nullptr; - } - - _Proxy._Release(); - } - - _CONSTEXPR20 void _Move_assign_unequal_alloc(vector& _Right) { - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - auto& _Right_data = _Right._Mypair._Myval2; - - const pointer _First = _Right_data._Myfirst; - const pointer _Last = _Right_data._Mylast; - const auto _Newsize = static_cast(_Last - _First); - - pointer& _Myfirst = _My_data._Myfirst; - pointer& _Mylast = _My_data._Mylast; - - constexpr bool _Nothrow_construct = - conjunction_v, _Uses_default_construct<_Alloc, _Ty*, _Ty>>; - - _My_data._Orphan_all(); - const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { - _Clear_and_reserve_geometric(_Newsize); - if constexpr (_Nothrow_construct) { - _Mylast = _Uninitialized_move(_First, _Last, _Myfirst, _Al); - _ASAN_VECTOR_CREATE; - } else { - _ASAN_VECTOR_CREATE_GUARD; - _Mylast = _Uninitialized_move(_First, _Last, _Myfirst, _Al); - } - - return; - } - - const auto _Oldsize = static_cast(_Mylast - _Myfirst); - if (_Newsize > _Oldsize) { - const pointer _Mid = _First + _Oldsize; - _STD _Move_unchecked(_First, _Mid, _Myfirst); - - if constexpr (_Nothrow_construct) { - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Uninitialized_move(_Mid, _Last, _Mylast, _Al); - } else { - _ASAN_VECTOR_EXTEND_GUARD(_Newsize); - _Mylast = _Uninitialized_move(_Mid, _Last, _Mylast, _Al); - _ASAN_VECTOR_RELEASE_GUARD; - } - } else { - const pointer _Newlast = _Myfirst + _Newsize; - _STD _Move_unchecked(_First, _Last, _Myfirst); - _Destroy_range(_Newlast, _Mylast, _Al); - _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); - _Mylast = _Newlast; - } - } - - [[noreturn]] static void _Xlength() { - _Xlength_error("vector too long"); - } - - [[noreturn]] static void _Xrange() { - _Xout_of_range("invalid vector subscript"); - } - -#if _ITERATOR_DEBUG_LEVEL == 2 - _CONSTEXPR20 void _Orphan_range_unlocked(pointer _First, pointer _Last) const { - _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; - while (*_Pnext) { - const auto _Pnextptr = static_cast(**_Pnext)._Ptr; - const auto _Temp = *_Pnext; - if (_Pnextptr < _First || _Last < _Pnextptr) { // skip the iterator - _Pnext = &_Temp->_Mynextiter; - } else { // orphan the iterator - _Temp->_Myproxy = nullptr; - *_Pnext = _Temp->_Mynextiter; - } - } - } - - void _Orphan_range_locked(pointer _First, pointer _Last) const { - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_range_unlocked(_First, _Last); - } - - _CONSTEXPR20 void _Orphan_range(pointer _First, pointer _Last) const { - // orphan iterators within specified (inclusive) range -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - _Orphan_range_unlocked(_First, _Last); - } else -#endif // _HAS_CXX20 - { - _Orphan_range_locked(_First, _Last); - } - } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv - _CONSTEXPR20 void _Orphan_range(pointer, pointer) const {} -#endif // _ITERATOR_DEBUG_LEVEL != 2 - - _NODISCARD _CONSTEXPR20 _Alty& _Getal() noexcept { - return _Mypair._Get_first(); - } - - _NODISCARD _CONSTEXPR20 const _Alty& _Getal() const noexcept { - return _Mypair._Get_first(); - } - - _NODISCARD _CONSTEXPR20 iterator _Make_iterator(const pointer _Ptr) noexcept { - return iterator(_Ptr, _STD addressof(_Mypair._Myval2)); - } - - _NODISCARD _CONSTEXPR20 iterator _Make_iterator_offset(const size_type _Offset) noexcept { - // return the iterator begin() + _Offset without a debugging check - auto& _My_data = _Mypair._Myval2; - return iterator(_My_data._Myfirst + _Offset, _STD addressof(_My_data)); - } - - _Compressed_pair<_Alty, _Scary_val> _Mypair; -}; - -#if _HAS_CXX17 -template >, - enable_if_t, _Is_allocator<_Alloc>>, int> = 0> -vector(_Iter, _Iter, _Alloc = _Alloc()) -> vector<_Iter_value_t<_Iter>, _Alloc>; -#endif // _HAS_CXX17 - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 -template <_RANGES input_range _Rng, class _Alloc = allocator<_RANGES range_value_t<_Rng>>, - enable_if_t<_Is_allocator<_Alloc>::value, int> = 0> -vector(from_range_t, _Rng&&, _Alloc = _Alloc()) -> vector<_RANGES range_value_t<_Rng>, _Alloc>; -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - -template -class vector; - -using _Vbase = unsigned int; // word type for vector representation - -_INLINE_VAR constexpr int _VBITS = 8 * sizeof(_Vbase); // at least CHAR_BITS bits per word - -_EXPORT_STD template -_NODISCARD _CONSTEXPR20 bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - if (_Left.size() != _Right.size()) { - return false; - } - - if constexpr (is_same_v<_Ty, bool>) { - return _STD equal( - _Left._Myvec._Unchecked_begin(), _Left._Myvec._Unchecked_end(), _Right._Myvec._Unchecked_begin()); - } else { - return _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); - } -} - -#if !_HAS_CXX20 -template -_NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - return !(_Left == _Right); -} -#endif // !_HAS_CXX20 - -// Optimize vector lexicographical comparisons. - -// There are several endianness/ordering issues to consider here. -// * Machine endianness is irrelevant. (That affects how an unsigned int is stored -// as a sequence of bytes. While all of our supported architectures are little-endian, -// that's irrelevant as long as we avoid reinterpreting unsigned int as a sequence of bytes.) -// * Appending bits to vector eventually appends words to its underlying storage. -// For example, vb[10] is stored within vb._Myvec[0], while vb[100] is stored within vb._Myvec[3]. -// This allows us to translate lexicographical comparisons from theoretical bits to physical words. -// * Unsigned integers are written and compared as big-endian (most significant bit first). -// For example, 0x10u > 0x07u. -// * However, vector packs bits into words as little-endian (least significant bit first). -// For example, vector{false, true, true, true} stores 0b0000'0000'0000'0000'0000'0000'0000'1110u. -// We could bit-reverse words before comparing, but we just need to find the least significant bit that differs. - -template -struct _Vbase_compare_three_way { - _NODISCARD constexpr _Ret operator()(const _Vbase _Left, const _Vbase _Right) const noexcept { - const _Vbase _Differing_bits = _Left ^ _Right; - - if (_Differing_bits == 0) { // improves _Countr_zero codegen below -#ifdef __cpp_lib_concepts - return strong_ordering::equal; -#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv - return 0; -#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ - } - - const int _Bit_index = _Countr_zero(_Differing_bits); // number of least significant bits that match - _STL_INTERNAL_CHECK(_Bit_index < _VBITS); // because we return early for equality - - const _Vbase _Mask = _Vbase{1} << _Bit_index; // selects the least significant bit that differs - - // Instead of comparing (_Left & _Mask) to (_Right & _Mask), we know that exactly one side will be zero. -#ifdef __cpp_lib_concepts - return (_Left & _Mask) == 0 ? strong_ordering::less : strong_ordering::greater; -#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv - return (_Left & _Mask) == 0 ? -1 : 1; -#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ - } -}; - -#ifdef __cpp_lib_concepts -_EXPORT_STD template -_NODISCARD constexpr _Synth_three_way_result<_Ty> operator<=>( - const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - if constexpr (is_same_v<_Ty, bool>) { - // This optimization works because vector "trims" its underlying storage by zeroing out unused bits. - const auto _Min_word_size = (_STD min)(_Left._Myvec.size(), _Right._Myvec.size()); - const auto _Left_words = _Left._Myvec._Unchecked_begin(); - const auto _Right_words = _Right._Myvec._Unchecked_begin(); - - using _Comp = _Vbase_compare_three_way; - - const strong_ordering _Word_comparison = _STD lexicographical_compare_three_way( - _Left_words, _Left_words + _Min_word_size, _Right_words, _Right_words + _Min_word_size, _Comp{}); - - if (_Word_comparison != 0) { - return _Word_comparison; - } - - return _Left.size() <=> _Right.size(); - } else { - return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end(), - _Right._Unchecked_begin(), _Right._Unchecked_end(), _Synth_three_way{}); - } -} -#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv -template -_NODISCARD _CONSTEXPR20 bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - if constexpr (is_same_v<_Ty, bool>) { - // This optimization works because vector "trims" its underlying storage by zeroing out unused bits. - auto _First = _Left._Myvec._Unchecked_begin(); - auto _Other = _Right._Myvec._Unchecked_begin(); - - const auto _Last = _First + (_STD min)(_Left._Myvec.size(), _Right._Myvec.size()); - - for (; _First != _Last; ++_First, (void) ++_Other) { - using _Comp = _Vbase_compare_three_way; - const auto _Result = _Comp{}(*_First, *_Other); - - if (_Result < 0) { - return true; - } else if (_Result > 0) { - return false; - } - } - - return _Left.size() < _Right.size(); - } else { - return _STD lexicographical_compare( - _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); - } -} - -template -_NODISCARD _CONSTEXPR20 bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - return _Right < _Left; -} - -template -_NODISCARD _CONSTEXPR20 bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - return !(_Right < _Left); -} - -template -_NODISCARD _CONSTEXPR20 bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { - return !(_Left < _Right); -} -#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ - -_EXPORT_STD template -_CONSTEXPR20 void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { - _Left.swap(_Right); -} - -#if _HAS_CXX20 -_EXPORT_STD template -constexpr vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { - return _Erase_remove(_Cont, _Val); -} - -_EXPORT_STD template -constexpr vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { - return _Erase_remove_if(_Cont, _Pass_fn(_Pred)); -} -#endif // _HAS_CXX20 - -template -struct _Wrap_alloc { // TRANSITION, ABI compat, preserves symbol names of vector::iterator - using _Alloc = _Alloc0; -}; - -template -class _Vb_iter_base : public _Iterator_base { - // store information common to reference and iterators -public: - using _Alvbase = typename _Alvbase_wrapped::_Alloc; - using _Size_type = typename allocator_traits<_Alvbase>::size_type; - using _Difference_type = typename allocator_traits<_Alvbase>::difference_type; - using _Mycont = vector>; - - static constexpr _Difference_type _VBITS_DIFF = _VBITS; - - _CONSTEXPR20 _Vb_iter_base() = default; - - _CONSTEXPR20 _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept - : _Myptr(_Ptr), _Myoff(_Off) { - this->_Adopt(_Mypvbool); - } - - _CONSTEXPR20 void _Advance(_Size_type _Off) noexcept { - _Myoff += _Off; - _Myptr += _Myoff / _VBITS; - _Myoff %= _VBITS; - } - -#if _ITERATOR_DEBUG_LEVEL != 0 - _CONSTEXPR20 _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { - return static_cast<_Difference_type>(_VBITS_DIFF * (_Myptr - _Cont->_Myvec.data()) + _Myoff); - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - const _Vbase* _Myptr = nullptr; - _Size_type _Myoff = 0; -}; - -template -class _Vb_reference : public _Vb_iter_base<_Alvbase_wrapped> { - // reference to a bit within a base word -private: - using _Mybase = _Vb_iter_base<_Alvbase_wrapped>; - using _Mycont = typename _Mybase::_Mycont; - using _Difference_type = typename _Mybase::_Difference_type; - - // TRANSITION, ABI: non-trivial constructor - _CONSTEXPR20 _Vb_reference() = default; - -public: - _CONSTEXPR20 _Vb_reference(const _Vb_reference&) = default; - - _CONSTEXPR20 _Vb_reference(const _Mybase& _Right) noexcept - : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} - - _CONSTEXPR20 _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { - return *this = static_cast(_Right); - } - - _CONSTEXPR20 _Vb_reference& operator=(bool _Val) noexcept { - if (_Val) { - *const_cast<_Vbase*>(_Getptr()) |= _Mask(); - } else { - *const_cast<_Vbase*>(_Getptr()) &= ~_Mask(); - } - - return *this; - } - -#if _HAS_CXX23 - constexpr const _Vb_reference& operator=(bool _Val) const noexcept { - if (_Val) { - *const_cast<_Vbase*>(_Getptr()) |= _Mask(); - } else { - *const_cast<_Vbase*>(_Getptr()) &= ~_Mask(); - } - - return *this; - } -#endif // _HAS_CXX23 - - _CONSTEXPR20 void flip() noexcept { - *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); - } - - _CONSTEXPR20 operator bool() const noexcept { - return (*_Getptr() & _Mask()) != 0; - } - - _CONSTEXPR20 const _Vbase* _Getptr() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return this->_Myptr; - } - - friend _CONSTEXPR20 void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { - bool _Val = _Left; // NOT _STD swap - _Left = _Right; - _Right = _Val; - } - -protected: - _CONSTEXPR20 _Vbase _Mask() const noexcept { - return static_cast<_Vbase>(1) << this->_Myoff; - } -}; - -template -class _Vb_const_iterator : public _Vb_iter_base<_Alvbase_wrapped> { -private: - using _Mybase = _Vb_iter_base<_Alvbase_wrapped>; - -public: - using _Mycont = typename _Mybase::_Mycont; - using _Difference_type = typename _Mybase::_Difference_type; - using _Size_type = typename _Mybase::_Size_type; - using _Reft = _Vb_reference<_Alvbase_wrapped>; - using const_reference = bool; - - using iterator_category = random_access_iterator_tag; - using value_type = bool; - using difference_type = typename _Mybase::_Difference_type; - using pointer = const_reference*; - using reference = const_reference; - - _CONSTEXPR20 _Vb_const_iterator() = default; - - _CONSTEXPR20 _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept - : _Mybase(_Ptr, 0, _Mypvbool) {} - - _NODISCARD _CONSTEXPR20 const_reference operator*() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return _Reft(*this); - } - - _CONSTEXPR20 _Vb_const_iterator& operator++() noexcept { - _Inc(); - return *this; - } - - _CONSTEXPR20 _Vb_const_iterator operator++(int) noexcept { - _Vb_const_iterator _Tmp = *this; - _Inc(); - return _Tmp; - } - - _CONSTEXPR20 _Vb_const_iterator& operator--() noexcept { - _Dec(); - return *this; - } - - _CONSTEXPR20 _Vb_const_iterator operator--(int) noexcept { - _Vb_const_iterator _Tmp = *this; - _Dec(); - return _Tmp; - } - - _CONSTEXPR20 _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - if (_Off != 0) { - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); - const auto _Start_offset = this->_Total_off(_Cont); - if (_Off < 0) { - _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); - } else if (0 < _Off) { - _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), - "cannot seek vector iterator after end"); - } - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - if (_Off < 0 && this->_Myoff < 0 - static_cast<_Size_type>(_Off)) { // add negative increment - this->_Myoff += static_cast<_Size_type>(_Off); - this->_Myptr -= 1 + (static_cast<_Size_type>(-1) - this->_Myoff) / _VBITS; - this->_Myoff %= _VBITS; - } else { // add non-negative increment - this->_Myoff += static_cast<_Size_type>(_Off); - this->_Myptr += this->_Myoff / _VBITS; - this->_Myoff %= _VBITS; - } - return *this; - } - - _NODISCARD _CONSTEXPR20 _Vb_const_iterator operator+(const difference_type _Off) const noexcept { - _Vb_const_iterator _Tmp = *this; - _Tmp += _Off; - return _Tmp; - } - - _NODISCARD_FRIEND _CONSTEXPR20 _Vb_const_iterator operator+( - const difference_type _Off, _Vb_const_iterator _Right) noexcept { - _Right += _Off; - return _Right; - } - - _CONSTEXPR20 _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { - return *this += -_Off; - } - - _NODISCARD _CONSTEXPR20 _Vb_const_iterator operator-(const difference_type _Off) const noexcept { - _Vb_const_iterator _Tmp = *this; - _Tmp -= _Off; - return _Tmp; - } - - _NODISCARD _CONSTEXPR20 difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { - _Compat(_Right); - return static_cast(_Mybase::_VBITS_DIFF * (this->_Myptr - _Right._Myptr)) - + static_cast(this->_Myoff) - static_cast(_Right._Myoff); - } - - _NODISCARD _CONSTEXPR20 const_reference operator[](const difference_type _Off) const noexcept { - return *(*this + _Off); - } - - _NODISCARD _CONSTEXPR20 bool operator==(const _Vb_const_iterator& _Right) const noexcept { - _Compat(_Right); - return this->_Myptr == _Right._Myptr && this->_Myoff == _Right._Myoff; - } - -#if _HAS_CXX20 - _NODISCARD constexpr strong_ordering operator<=>(const _Vb_const_iterator& _Right) const noexcept { - _Compat(_Right); - if (const auto _CmpResult = this->_Myptr <=> _Right._Myptr; _CmpResult != 0) { - return _CmpResult; - } - return this->_Myoff <=> _Right._Myoff; - } -#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv - _NODISCARD bool operator!=(const _Vb_const_iterator& _Right) const noexcept { - return !(*this == _Right); - } - - _NODISCARD bool operator<(const _Vb_const_iterator& _Right) const noexcept { - _Compat(_Right); - return this->_Myptr < _Right._Myptr || (this->_Myptr == _Right._Myptr && this->_Myoff < _Right._Myoff); - } - - _NODISCARD bool operator>(const _Vb_const_iterator& _Right) const noexcept { - return _Right < *this; - } - - _NODISCARD bool operator<=(const _Vb_const_iterator& _Right) const noexcept { - return !(_Right < *this); - } - - _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { - return !(*this < _Right); - } -#endif // !_HAS_CXX20 - - _CONSTEXPR20 void _Compat(const _Vb_const_iterator& _Right) const noexcept { - // test for compatible iterator pair -#if _ITERATOR_DEBUG_LEVEL == 0 - (void) _Right; -#else - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); -#endif - } - -#if _ITERATOR_DEBUG_LEVEL != 0 - using _Prevent_inheriting_unwrap = _Vb_const_iterator; - - friend _CONSTEXPR20 void _Verify_range(const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { - // note _Compat check inside <= - _STL_VERIFY(_First <= _Last, "vector iterator range transposed"); - } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - _CONSTEXPR20 void _Dec() noexcept { // decrement bit position -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - if (this->_Myoff != 0) { - --this->_Myoff; - } else { // move to previous word - this->_Myoff = _VBITS - 1; - --this->_Myptr; - } - } - - _CONSTEXPR20 void _Inc() noexcept { // increment bit position -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "cannot increment vector end iterator"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - if (this->_Myoff < _VBITS - 1) { - ++this->_Myoff; - } else { // move to next word - this->_Myoff = 0; - ++this->_Myptr; - } - } -}; - -template -class _Vb_iterator : public _Vb_const_iterator<_Alvbase_wrapped> { -public: - using _Mybase = _Vb_const_iterator<_Alvbase_wrapped>; - using _Mycont = typename _Mybase::_Mycont; - using _Difference_type = typename _Mybase::_Difference_type; - - using _Reft = _Vb_reference<_Alvbase_wrapped>; - using const_reference = bool; - - using iterator_category = random_access_iterator_tag; - using value_type = bool; - using difference_type = typename _Mybase::difference_type; - using pointer = _Reft*; - using reference = _Reft; - - using _Mybase::_Mybase; - - _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - const auto _Cont = static_cast(this->_Getcont()); - _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - return _Reft(*this); - } - - _CONSTEXPR20 _Vb_iterator& operator++() noexcept { - _Mybase::operator++(); - return *this; - } - - _CONSTEXPR20 _Vb_iterator operator++(int) noexcept { - _Vb_iterator _Tmp = *this; - _Mybase::operator++(); - return _Tmp; - } - - _CONSTEXPR20 _Vb_iterator& operator--() noexcept { - _Mybase::operator--(); - return *this; - } - - _CONSTEXPR20 _Vb_iterator operator--(int) noexcept { - _Vb_iterator _Tmp = *this; - _Mybase::operator--(); - return _Tmp; - } - - _CONSTEXPR20 _Vb_iterator& operator+=(const difference_type _Off) noexcept { - _Mybase::operator+=(_Off); - return *this; - } - - _NODISCARD _CONSTEXPR20 _Vb_iterator operator+(const difference_type _Off) const noexcept { - _Vb_iterator _Tmp = *this; - _Tmp += _Off; - return _Tmp; - } - - _NODISCARD_FRIEND _CONSTEXPR20 _Vb_iterator operator+(const difference_type _Off, _Vb_iterator _Right) noexcept { - _Right += _Off; - return _Right; - } - - _CONSTEXPR20 _Vb_iterator& operator-=(const difference_type _Off) noexcept { - _Mybase::operator-=(_Off); - return *this; - } - - using _Mybase::operator-; - - _NODISCARD _CONSTEXPR20 _Vb_iterator operator-(const difference_type _Off) const noexcept { - _Vb_iterator _Tmp = *this; - _Tmp -= _Off; - return _Tmp; - } - - _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { - return *(*this + _Off); - } - - using _Prevent_inheriting_unwrap = _Vb_iterator; -}; - -template -class _Vb_val : public _Container_base { -public: - using _Alvbase = _Rebind_alloc_t<_Alloc, _Vbase>; - using _Alvbase_traits = allocator_traits<_Alvbase>; - using _Vectype = vector<_Vbase, _Alvbase>; - using _Alvbase_wrapped = _Wrap_alloc<_Alvbase>; - using size_type = typename _Alvbase_traits::size_type; - - _CONSTEXPR20 _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(const _Alloc& _Al) noexcept : _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(size_type _Count, const bool& _Val) - : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) - : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0), static_cast<_Alvbase>(_Al)), _Mysize(0) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) - : _Myvec(_Right._Myvec, static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) - : _Myvec(_STD move(_Right._Myvec)), _Mysize(_STD exchange(_Right._Mysize, size_type{0})) { - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept( - is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) - : _Myvec(_STD move(_Right._Myvec), static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { - if (_Right._Myvec.empty()) { - // we took _Right's buffer, so zero out size - _Right._Mysize = 0; - } - - this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); - } - - _CONSTEXPR20 ~_Vb_val() noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - this->_Orphan_all(); - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alvbase, this->_Getal()); - _Delete_plain_internal(_Alproxy, _STD exchange(this->_Myproxy, nullptr)); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - } - - _CONSTEXPR20 _Alvbase& _Getal() noexcept { - return _Myvec._Getal(); - } - - _CONSTEXPR20 const _Alvbase& _Getal() const noexcept { - return _Myvec._Getal(); - } - - static _CONSTEXPR20 size_type _Nw(size_type _Count) noexcept { - return (_Count + _VBITS - 1) / _VBITS; - } - - _CONSTEXPR20 void _Emplace_back_unchecked(const _Vbase _Val) noexcept { - _STL_INTERNAL_CHECK(_Myvec.size() < _Myvec.capacity()); - _Myvec._Emplace_back_with_unused_capacity(_Val); - } - - _Vectype _Myvec; // base vector of words - size_type _Mysize; // current length of sequence -}; - -template -class vector : public _Vb_val<_Alloc> { -public: - static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v, - _MISMATCHED_ALLOCATOR_MESSAGE("vector", "bool")); - - using _Mybase = _Vb_val<_Alloc>; - using _Alvbase_wrapped = typename _Mybase::_Alvbase_wrapped; - using _Alvbase = typename _Mybase::_Alvbase; - using _Alvbase_traits = typename _Mybase::_Alvbase_traits; - - using size_type = typename _Alvbase_traits::size_type; - using difference_type = typename _Alvbase_traits::difference_type; - using allocator_type = _Alloc; - - using reference = _Vb_reference<_Alvbase_wrapped>; - using const_reference = bool; - using value_type = bool; - - using _Reft = reference; - using iterator = _Vb_iterator<_Alvbase_wrapped>; - using const_iterator = _Vb_const_iterator<_Alvbase_wrapped>; - - using pointer = iterator; - using const_pointer = const_iterator; - using reverse_iterator = _STD reverse_iterator; - using const_reverse_iterator = _STD reverse_iterator; - - enum { _EEN_VBITS = _VBITS }; // helper for expression evaluator - - _CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Alloc>) : _Mybase(_Alloc()) {} - - _CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept : _Mybase(_Al) {} - - _CONSTEXPR20 explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) - : _Mybase(_Count, false, _Al) { - _Trim(_Count); - } - - _CONSTEXPR20 vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) - : _Mybase(_Count, _Val, _Al) { - _Trim(_Count); - } - - _CONSTEXPR20 vector(const vector& _Right) : _Mybase(_Right) {} - - _CONSTEXPR20 vector(const vector& _Right, const _Identity_t<_Alloc>& _Al) : _Mybase(_Right, _Al) {} - - template , int> = 0> - _CONSTEXPR20 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { - insert(begin(), _First, _Last); - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range _Rng> - constexpr vector(from_range_t, _Rng&& _Range, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { - if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); - } else { - _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 vector(vector&& _Right) noexcept : _Mybase(_STD move(_Right)) { - this->_Swap_proxy_and_iterators(_Right); - } - - _CONSTEXPR20 vector(vector&& _Right, const _Identity_t<_Alloc>& _Al) noexcept( - is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) // strengthened - : _Mybase(_STD move(_Right), _Al) { - if constexpr (!_Alvbase_traits::is_always_equal::value) { - if (this->_Getal() != _Right._Getal()) { - return; - } - } - - this->_Swap_proxy_and_iterators(_Right); - } - - _CONSTEXPR20 vector& operator=(vector&& _Right) noexcept( - _Choose_pocma_v<_Alvbase> != _Pocma_values::_No_propagate_allocators) { - if (this == _STD addressof(_Right)) { - return *this; - } - -#if _ITERATOR_DEBUG_LEVEL == 0 - this->_Myvec = _STD move(_Right._Myvec); - this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - this->_Orphan_all(); - auto& _Al = this->_Getal(); - auto& _Right_al = _Right._Getal(); - constexpr auto _Pocma_val = _Choose_pocma_v<_Alvbase>; - if constexpr (_Pocma_val == _Pocma_values::_Propagate_allocators) { - using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; - if (_Al != _Right_al) { // reload proxy - // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 - _Alproxy_type _Oldal(_Al); - _Alproxy_type _Right_proxy_al(_Right_al); - _Container_proxy_ptr<_Alvbase> _Proxy(_Right_proxy_al, _Leave_proxy_unbound{}); - this->_Myvec = _STD move(_Right._Myvec); - this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); - _Proxy._Bind(_Oldal, this); - this->_Swap_proxy_and_iterators(_Right); - return *this; - } - } else if constexpr (_Pocma_val == _Pocma_values::_No_propagate_allocators) { - this->_Myvec = _STD move(_Right._Myvec); - this->_Mysize = _Right._Mysize; - if (_Right._Myvec.empty()) { - // we took _Right's buffer, so zero out size - _Right._Mysize = 0; - } - - if (_Al == _Right_al) { - this->_Swap_proxy_and_iterators(_Right); - } - return *this; - } - - this->_Myvec = _STD move(_Right._Myvec); - this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); - this->_Swap_proxy_and_iterators(_Right); - -#endif // _ITERATOR_DEBUG_LEVEL == 0 - return *this; - } - - template - _CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) { - bool _Tmp(_STD forward<_Valty>(_Val)...); - push_back(_Tmp); - -#if _HAS_CXX17 - return back(); -#endif // _HAS_CXX17 - } - - template - _CONSTEXPR20 iterator emplace(const_iterator _Where, _Valty&&... _Val) { - bool _Tmp(_STD forward<_Valty>(_Val)...); - return insert(_Where, _Tmp); - } - - _CONSTEXPR20 vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) : _Mybase(0, false, _Al) { - insert(begin(), _Ilist.begin(), _Ilist.end()); - } - - _CONSTEXPR20 vector& operator=(initializer_list _Ilist) { - assign(_Ilist.begin(), _Ilist.end()); - return *this; - } - - _CONSTEXPR20 void assign(initializer_list _Ilist) { - assign(_Ilist.begin(), _Ilist.end()); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, initializer_list _Ilist) { - return insert(_Where, _Ilist.begin(), _Ilist.end()); - } - - _CONSTEXPR20 ~vector() noexcept {} - - _CONSTEXPR20 vector& operator=(const vector& _Right) { - if (this == _STD addressof(_Right)) { - return *this; - } - -#if _ITERATOR_DEBUG_LEVEL == 0 - this->_Myvec = _Right._Myvec; - this->_Mysize = _Right._Mysize; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - this->_Orphan_all(); - auto& _Al = this->_Getal(); - auto& _Right_al = _Right._Getal(); - if constexpr (_Choose_pocca_v<_Alvbase>) { - if (_Al != _Right_al) { - // reload proxy - using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; - _Alproxy_type _Oldal(_Al); - _Alproxy_type _Right_proxy_al(_Right_al); - _Container_proxy_ptr<_Alvbase> _Proxy(_Right_proxy_al, _Leave_proxy_unbound{}); - this->_Myvec = _Right._Myvec; - this->_Mysize = _Right._Mysize; - _Proxy._Bind(_Oldal, this); - return *this; - } - } - - this->_Myvec = _Right._Myvec; - this->_Mysize = _Right._Mysize; -#endif // _ITERATOR_DEBUG_LEVEL == 0 - - return *this; - } - - _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW size_type _Count) { - this->_Myvec.reserve(this->_Nw(_Count)); - } - - _NODISCARD _CONSTEXPR20 size_type capacity() const noexcept { - return this->_Myvec.capacity() * _VBITS; - } - - _NODISCARD _CONSTEXPR20 iterator begin() noexcept { - return iterator(this->_Myvec.data(), this); - } - - _NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept { - return const_iterator(this->_Myvec.data(), this); - } - - _NODISCARD _CONSTEXPR20 iterator end() noexcept { - return begin() + static_cast(this->_Mysize); - } - - _NODISCARD _CONSTEXPR20 const_iterator end() const noexcept { - return begin() + static_cast(this->_Mysize); - } - - _NODISCARD _CONSTEXPR20 const_iterator cbegin() const noexcept { - return begin(); - } - - _NODISCARD _CONSTEXPR20 const_iterator cend() const noexcept { - return end(); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { - return rbegin(); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator crend() const noexcept { - return rend(); - } - - _NODISCARD _CONSTEXPR20 iterator _Unchecked_begin() noexcept { - return iterator(this->_Myvec.data(), this); - } - - _NODISCARD _CONSTEXPR20 const_iterator _Unchecked_begin() const noexcept { - return const_iterator(this->_Myvec.data(), this); - } - - _NODISCARD _CONSTEXPR20 iterator _Unchecked_end() noexcept { - return _Unchecked_begin() + static_cast(this->_Mysize); - } - - _NODISCARD _CONSTEXPR20 const_iterator _Unchecked_end() const noexcept { - return _Unchecked_begin() + static_cast(this->_Mysize); - } - - _CONSTEXPR20 void shrink_to_fit() { - if (this->_Myvec.capacity() != this->_Myvec.size()) { - this->_Orphan_all(); - this->_Myvec.shrink_to_fit(); - } - } - - _CONSTEXPR20 iterator _Make_iter(const_iterator _Where) noexcept { - iterator _Tmp = begin(); - if (0 < this->_Mysize) { - _Tmp += _Where - begin(); - } - - return _Tmp; - } - - _NODISCARD _CONSTEXPR20 reverse_iterator rbegin() noexcept { - return reverse_iterator(end()); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator(end()); - } - - _NODISCARD _CONSTEXPR20 reverse_iterator rend() noexcept { - return reverse_iterator(begin()); - } - - _NODISCARD _CONSTEXPR20 const_reverse_iterator rend() const noexcept { - return const_reverse_iterator(begin()); - } - - _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { - if (size() < _Newsize) { - _Insert_n(end(), _Newsize - size(), _Val); - } else if (_Newsize < size()) { - erase(begin() + static_cast(_Newsize), end()); - } - } - - _NODISCARD _CONSTEXPR20 size_type size() const noexcept { - return this->_Mysize; - } - - _NODISCARD _CONSTEXPR20 size_type max_size() const noexcept { - constexpr auto _Diff_max = static_cast((numeric_limits::max)()); - const size_type _Ints_max = this->_Myvec.max_size(); - if (_Ints_max > _Diff_max / _VBITS) { // max_size bound by difference_type limits - return _Diff_max; - } - - // max_size bound by underlying storage limits - return _Ints_max * _VBITS; - } - - _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { - return this->_Mysize == 0; - } - - _NODISCARD _CONSTEXPR20 allocator_type get_allocator() const noexcept { - return static_cast(this->_Myvec.get_allocator()); - } - - _NODISCARD _CONSTEXPR20 const_reference at(size_type _Off) const { - if (size() <= _Off) { - _Xran(); - } - - return (*this)[_Off]; - } - - _NODISCARD _CONSTEXPR20 reference at(size_type _Off) { - if (size() <= _Off) { - _Xran(); - } - - return (*this)[_Off]; - } - - _NODISCARD _CONSTEXPR20 const_reference operator[](size_type _Off) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - const_iterator _It = begin(); - _It._Advance(_Off); - return *_It; - } - - _NODISCARD _CONSTEXPR20 reference operator[](size_type _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - iterator _It = begin(); - _It._Advance(_Off); - return *_It; - } - - _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *begin(); - } - - _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *begin(); - } - - _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *(end() - 1); - } - - _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 - - return *(end() - 1); - } - - _CONSTEXPR20 void push_back(const bool& _Val) { - insert(end(), _Val); - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range _Rng> - constexpr void append_range(_Rng&& _Range) { - insert_range(end(), _STD forward<_Rng>(_Range)); - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { - erase(end() - 1); - } - - template , int> = 0> - _CONSTEXPR20 void assign(_Iter _First, _Iter _Last) { - clear(); - insert(begin(), _First, _Last); - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template - constexpr void _Assign_counted_range(_Iter _First, const size_type _Count) { - _STL_INTERNAL_CHECK(this->_Myvec.empty()); - this->_Myvec.reserve(this->_Nw(_Count)); - _Vbase _Accum = 0; - _Vbase _Mask = 1; - for (size_type _Idx = 0; _Idx < _Count; ++_Idx) { - const bool _Tmp = *_First; - ++_First; - _Accum |= _Tmp ? _Mask : _Vbase{0}; - if ((_Mask <<= 1) == 0) { - this->_Emplace_back_unchecked(_Accum); - _Accum = 0; - _Mask = 1; - } - } - - if (_Count % _VBITS != 0) { - this->_Emplace_back_unchecked(_Accum); - } - this->_Mysize = _Count; - } - - template - constexpr void _Assign_uncounted_range(_Iter _First, const _Sent _Last) { - _STL_INTERNAL_CHECK(this->_Myvec.empty()); - size_type _Count = 0; - _Vbase _Accum = 0; - _Vbase _Mask = 1; - for (; _First != _Last; ++_Count) { - const bool _Tmp = *_First; - ++_First; - _Accum |= _Tmp ? _Mask : _Vbase{0}; - if ((_Mask <<= 1) == 0) { - this->_Myvec.push_back(_Accum); - _Accum = 0; - _Mask = 1; - } - } - - if (_Count % _VBITS != 0) { - this->_Myvec.push_back(_Accum); - } - this->_Mysize = _Count; - } - - template <_Container_compatible_range _Rng> - constexpr void assign_range(_Rng&& _Range) { - clear(); - if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); - } else { - _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); - } - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { - clear(); - _Insert_n(begin(), _Count, _Val); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, const bool& _Val) { - return _Insert_n(_Where, size_type{1}, _Val); - } - - _CONSTEXPR20 iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { - return _Insert_n(_Where, _Count, _Val); - } - - template , int> = 0> - _CONSTEXPR20 iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { - const difference_type _Saved_offset = _Where - begin(); - _Adl_verify_range(_First, _Last); - auto _UFirst = _Get_unwrapped(_First); - const auto _ULast = _Get_unwrapped(_Last); - - if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { - const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - const auto _Off = static_cast(_Insert_x(_Where, _Count)); - _STD _Copy_unchecked(_UFirst, _ULast, begin() + _Off); -#ifdef __cpp_lib_concepts - } else if constexpr (forward_iterator<_Iter>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); - const auto _Count = _Convert_size(_Length); - const auto _Off = static_cast(_Insert_x(_Where, _Count)); - _STD _Copy_unchecked(_UFirst, _ULast, begin() + _Off); -#endif // defined(__cpp_lib_concepts) - } else { - const auto _Old_size = this->_Mysize; - for (; _UFirst != _ULast; ++_UFirst) { - emplace_back(*_UFirst); - } -#if _ITERATOR_DEBUG_LEVEL == 2 - _Orphan_range(static_cast(_Saved_offset), _Old_size); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - _STD rotate(begin() + _Saved_offset, begin() + static_cast(_Old_size), end()); - } - - return begin() + _Saved_offset; - } - -#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 - template <_Container_compatible_range _Rng> - constexpr iterator insert_range(const_iterator _Where, _Rng&& _Range) { - const difference_type _Old_off = _Where - begin(); - - if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { - const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); - const auto _Count = _Convert_size(_Length); - const auto _Off = static_cast(_Insert_x(_Where, _Count)); - _Copy_n_unchecked4(_RANGES _Ubegin(_Range), _Count, begin() + _Off); - } else { - auto _UFirst = _RANGES _Ubegin(_Range); - const auto _ULast = _RANGES _Uend(_Range); - const auto _Old_size = this->_Mysize; - for (; _UFirst != _ULast; ++_UFirst) { - emplace_back(*_UFirst); - } -#if _ITERATOR_DEBUG_LEVEL == 2 - _Orphan_range(static_cast(_Old_off), _Old_size); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - _STD rotate(begin() + _Old_off, begin() + static_cast(_Old_size), end()); - } - - return begin() + _Old_off; - } -#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - - _CONSTEXPR20 iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { - iterator _Where = _Make_iter(_Where_arg); - difference_type _Off = _Where - begin(); - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(end() > _Where, "vector erase iterator outside range"); - _STD copy(_Next_iter(_Where), end(), _Where); - _Orphan_range(static_cast(_Off), this->_Mysize); - -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - _STD copy(_Next_iter(_Where), end(), _Where); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ - - _Trim(this->_Mysize - 1); - return begin() + _Off; - } - - _CONSTEXPR20 iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept - /* strengthened */ { - iterator _First = _Make_iter(_First_arg); - iterator _Last = _Make_iter(_Last_arg); - difference_type _Off = _First - begin(); - - if (_First != _Last) { // worth doing, copy down over hole -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Last >= _First && end() >= _Last, "vector erase iterator outside range"); - iterator _Next = _STD copy(_Last, end(), _First); - const auto _Newsize = static_cast(_Next - begin()); - _Orphan_range(_Newsize, this->_Mysize); - _Trim(_Newsize); - -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - iterator _Next = _STD copy(_Last, end(), _First); - _Trim(static_cast(_Next - begin())); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ - } - return begin() + _Off; - } - - _CONSTEXPR20 void clear() noexcept { - this->_Orphan_all(); - this->_Myvec.clear(); - this->_Mysize = 0; - } - - _CONSTEXPR20 void flip() noexcept { // toggle all elements - for (auto& _Elem : this->_Myvec) { - _Elem = ~_Elem; - } - - _Trim(this->_Mysize); - } - - _CONSTEXPR20 void swap(vector& _Right) noexcept /* strengthened */ { - if (this != _STD addressof(_Right)) { - this->_Swap_proxy_and_iterators(_Right); - this->_Myvec.swap(_Right._Myvec); - _STD swap(this->_Mysize, _Right._Mysize); - } - } - - static _CONSTEXPR20 void swap(reference _Left, reference _Right) noexcept { - bool _Val = _Left; // NOT _STD swap - _Left = _Right; - _Right = _Val; - } - - friend hash>; - - _CONSTEXPR20 iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { - size_type _Off = _Insert_x(_Where, _Count); - const auto _Result = begin() + static_cast(_Off); - _STD fill_n(_Result, _Count, _Val); - return _Result; - } - - _CONSTEXPR20 size_type _Insert_x(const_iterator _Where, size_type _Count) { - const difference_type _Off = _Where - begin(); - -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(end() >= _Where, "vector insert iterator outside range"); - const bool _Realloc = capacity() - size() < _Count; -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - if (_Count != 0) { - if (max_size() - size() < _Count) { - _Xlen(); // result too long - } - -#if _ITERATOR_DEBUG_LEVEL == 2 - _Orphan_range(static_cast(_Realloc ? 0 : _Off), this->_Mysize); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - this->_Myvec.resize(this->_Nw(size() + _Count), 0); - if (empty()) { - this->_Mysize += _Count; - } else { // make room and copy down suffix - iterator _Oldend = end(); - this->_Mysize += _Count; - _STD copy_backward(begin() + _Off, _Oldend, end()); - } - } - - return static_cast(_Off); - } - -#if _ITERATOR_DEBUG_LEVEL == 2 - _CONSTEXPR20 void _Orphan_range_unlocked(size_type _Offlo, size_type _Offhi) const { - const auto _Base = this->_Myvec.data(); - - _Iterator_base12** _Pnext = &this->_Myproxy->_Myfirstiter; - while (*_Pnext) { // test offset from beginning of vector - const auto& _Pnextiter = static_cast(**_Pnext); - const auto _Temp = *_Pnext; - if (!_Pnextiter._Myptr) { // orphan the iterator - _Temp->_Myproxy = nullptr; - *_Pnext = _Temp->_Mynextiter; - continue; - } - const auto _Off = - static_cast(const_iterator::_VBITS_DIFF * (_Pnextiter._Myptr - _Base)) + _Pnextiter._Myoff; - if (_Off < _Offlo || _Offhi < _Off) { - _Pnext = &_Temp->_Mynextiter; - } else { // orphan the iterator - _Temp->_Myproxy = nullptr; - *_Pnext = _Temp->_Mynextiter; - } - } - } - - void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { - _Lockit _Lock(_LOCK_DEBUG); - _Orphan_range_unlocked(_Offlo, _Offhi); - } - - _CONSTEXPR20 void _Orphan_range(size_type _Offlo, size_type _Offhi) const { -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - _Orphan_range_unlocked(_Offlo, _Offhi); - } else -#endif // _HAS_CXX20 - { - _Orphan_range_locked(_Offlo, _Offhi); - } - } -#endif // _ITERATOR_DEBUG_LEVEL == 2 - - _CONSTEXPR20 void _Trim(size_type _Size) { - if (max_size() < _Size) { - _Xlen(); // result too long - } - - const size_type _Words = this->_Nw(_Size); - if (_Words < this->_Myvec.size()) { - this->_Myvec.erase(this->_Myvec.begin() + static_cast(_Words), this->_Myvec.end()); - } - - this->_Mysize = _Size; - _Size %= _VBITS; - if (0 < _Size) { - this->_Myvec[_Words - 1] &= (static_cast<_Vbase>(1) << _Size) - 1; - } - } - - [[noreturn]] static void _Xlen() { - _Xlength_error("vector too long"); - } - - [[noreturn]] static void _Xran() { - _Xout_of_range("invalid vector subscript"); - } -}; - -template -struct hash> { - using _ARGUMENT_TYPE_NAME _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS = vector; - using _RESULT_TYPE_NAME _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS = size_t; - - _NODISCARD size_t operator()(const vector& _Keyval) const noexcept { - return _Hash_array_representation(_Keyval._Myvec.data(), _Keyval._Myvec.size()); - } -}; - -#if _HAS_CXX17 -namespace pmr { - _EXPORT_STD template - using vector = _STD vector<_Ty, polymorphic_allocator<_Ty>>; -} // namespace pmr -#endif // _HAS_CXX17 - -template -_INLINE_VAR constexpr bool _Is_vb_iterator<_Vb_iterator<_Alloc>, _RequiresMutable> = true; - -template -_INLINE_VAR constexpr bool _Is_vb_iterator<_Vb_const_iterator<_Alloc>, false> = true; - -template -_CONSTEXPR20 void _Fill_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { - // Set [_First, _Last) to _Val - if (_First == _Last) { - return; - } - - _Vbase* _VbFirst = const_cast<_Vbase*>(_First._Myptr); - _Vbase* const _VbLast = const_cast<_Vbase*>(_Last._Myptr); - - const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; - const auto _FirstDestMask = ~_FirstSourceMask; - const auto _FillVal = static_cast<_Vbase>(_Val ? -1 : 0); - - if (_VbFirst == _VbLast) { - // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _LastDestMask = ~_LastSourceMask; - const auto _SourceMask = _FirstSourceMask & _LastSourceMask; - const auto _DestMask = _FirstDestMask | _LastDestMask; - *_VbFirst = (*_VbFirst & _DestMask) | (_FillVal & _SourceMask); - return; - } - - *_VbFirst = (*_VbFirst & _FirstDestMask) | (_FillVal & _FirstSourceMask); - ++_VbFirst; - -#if _HAS_CXX20 - if (_STD is_constant_evaluated()) { - for (; _VbFirst != _VbLast; ++_VbFirst) { - *_VbFirst = _FillVal; - } - } else -#endif // _HAS_CXX20 - { - const auto _VbFirst_ch = reinterpret_cast(_VbFirst); - const auto _VbLast_ch = reinterpret_cast(_VbLast); - const auto _Count_ch = static_cast(_VbLast_ch - _VbFirst_ch); - const auto _ValChar = static_cast(_Val ? -1 : 0); - _CSTD memset(_VbFirst, _ValChar, _Count_ch); - _VbFirst = _VbLast; - } - - if (_Last._Myoff != 0) { - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _LastDestMask = ~_LastSourceMask; - *_VbFirst = (*_VbFirst & _LastDestMask) | (_FillVal & _LastSourceMask); - } -} - -template -_NODISCARD _CONSTEXPR20 _VbIt _Find_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { - // Find _Val in [_First, _Last) - if (_First == _Last) { - return _First; - } - - const _Vbase* _VbFirst = _First._Myptr; - const _Vbase* const _VbLast = _Last._Myptr; - - const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; - - if (_VbFirst == _VbLast) { - // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _SourceMask = _FirstSourceMask & _LastSourceMask; - const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask; - const auto _Count = _Countr_zero(_SelectVal); - return _Count == _VBITS ? _Last : _First + static_cast(_Count - _First._Myoff); - } - - const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask; - const auto _FirstCount = _Countr_zero(_FirstVal); - if (_FirstCount != _VBITS) { - return _First + static_cast(_FirstCount - _First._Myoff); - } - ++_VbFirst; - - _Iter_diff_t<_VbIt> _TotalCount = static_cast(_VBITS - _First._Myoff); - for (; _VbFirst != _VbLast; ++_VbFirst, _TotalCount += _VBITS) { - const auto _SelectVal = _Val ? *_VbFirst : ~*_VbFirst; - const auto _Count = _Countr_zero(_SelectVal); - if (_Count != _VBITS) { - return _First + (_TotalCount + _Count); - } - } - - if (_Last._Myoff != 0) { - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _LastVal = (_Val ? *_VbFirst : ~*_VbFirst) & _LastSourceMask; - const auto _Count = _Countr_zero(_LastVal); - if (_Count != _VBITS) { - return _First + (_TotalCount + _Count); - } - } - - return _Last; -} - -template -_NODISCARD _CONSTEXPR20 _Iter_diff_t<_VbIt> _Count_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { - if (_First == _Last) { - return 0; - } - - const _Vbase* _VbFirst = _First._Myptr; - const _Vbase* const _VbLast = _Last._Myptr; - - const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; - - if (_VbFirst == _VbLast) { - // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _SourceMask = _FirstSourceMask & _LastSourceMask; - const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask; - return _Popcount(_SelectVal); - } - - return _Select_popcount_impl<_Vbase>( - [_Last, _Val, _VbFirst, _VbLast, _FirstSourceMask](auto _Popcount_impl) mutable noexcept { - const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask; - _Iter_diff_t<_VbIt> _Count = _Popcount_impl(_FirstVal); - ++_VbFirst; - - for (; _VbFirst != _VbLast; ++_VbFirst) { - const auto _SelectVal = _Val ? *_VbFirst : ~*_VbFirst; - _Count += _Popcount_impl(_SelectVal); - } - - if (_Last._Myoff != 0) { - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); - const auto _LastVal = (_Val ? *_VbFirst : ~*_VbFirst) & _LastSourceMask; - _Count += _Popcount_impl(_LastVal); - } - - return _Count; - }); -} - -#undef _ASAN_VECTOR_MODIFY -#undef _ASAN_VECTOR_REMOVE -#undef _ASAN_VECTOR_CREATE -#undef _ASAN_VECTOR_CREATE_GUARD -#undef _ASAN_VECTOR_EXTEND_GUARD -#undef _ASAN_VECTOR_RELEASE_GUARD -#undef _INSERT_VECTOR_ANNOTATION -_STD_END - -#pragma pop_macro("new") -_STL_RESTORE_CLANG_WARNINGS -#pragma warning(pop) -#pragma pack(pop) -#endif // _STL_COMPILER_PREPROCESSOR -#endif // _VECTOR_ +// vector standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef _VECTOR_ +#define _VECTOR_ +#include +#if _STL_COMPILER_PREPROCESSOR +#include <__msvc_bit_utils.hpp> +#include <__msvc_sanitizer_annotate_container.hpp> +#include + +#if _HAS_CXX17 +#include +#endif // _HAS_CXX17 + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +_STD_BEGIN +template +class _Vector_const_iterator : public _Iterator_base { +public: +#ifdef __cpp_lib_concepts + using iterator_concept = contiguous_iterator_tag; +#endif // defined(__cpp_lib_concepts) + using iterator_category = random_access_iterator_tag; + using value_type = typename _Myvec::value_type; + using difference_type = typename _Myvec::difference_type; + using pointer = typename _Myvec::const_pointer; + using reference = const value_type&; + + using _Tptr = typename _Myvec::pointer; + + _CONSTEXPR20 _Vector_const_iterator() noexcept : _Ptr() {} + + _CONSTEXPR20 _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { + this->_Adopt(_Pvector); + } + + _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return *_Ptr; + } + + _NODISCARD _CONSTEXPR20 pointer operator->() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return _Ptr; + } + + _CONSTEXPR20 _Vector_const_iterator& operator++() noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); + _STL_VERIFY(_Mycont, "can't increment invalidated vector iterator"); + _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + ++_Ptr; + return *this; + } + + _CONSTEXPR20 _Vector_const_iterator operator++(int) noexcept { + _Vector_const_iterator _Tmp = *this; + ++*this; + return _Tmp; + } + + _CONSTEXPR20 _Vector_const_iterator& operator--() noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); + _STL_VERIFY(_Mycont, "can't decrement invalidated vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + --_Ptr; + return *this; + } + + _CONSTEXPR20 _Vector_const_iterator operator--(int) noexcept { + _Vector_const_iterator _Tmp = *this; + --*this; + return _Tmp; + } + + _CONSTEXPR20 void _Verify_offset(const difference_type _Off) const noexcept { +#if _ITERATOR_DEBUG_LEVEL == 0 + (void) _Off; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); + _STL_VERIFY(_Off == 0 || _Mycont, "cannot seek invalidated vector iterator"); + if (_Off < 0) { + _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); + } + + if (_Off > 0) { + _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); + } +#endif // _ITERATOR_DEBUG_LEVEL == 0 + } + + _CONSTEXPR20 _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { + _Verify_offset(_Off); + _Ptr += _Off; + return *this; + } + + _NODISCARD _CONSTEXPR20 _Vector_const_iterator operator+(const difference_type _Off) const noexcept { + _Vector_const_iterator _Tmp = *this; + _Tmp += _Off; + return _Tmp; + } + + _NODISCARD_FRIEND _CONSTEXPR20 _Vector_const_iterator operator+( + const difference_type _Off, _Vector_const_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + + _CONSTEXPR20 _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { + return *this += -_Off; + } + + _NODISCARD _CONSTEXPR20 _Vector_const_iterator operator-(const difference_type _Off) const noexcept { + _Vector_const_iterator _Tmp = *this; + _Tmp -= _Off; + return _Tmp; + } + + _NODISCARD _CONSTEXPR20 difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Ptr - _Right._Ptr; + } + + _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { + return *(*this + _Off); + } + + _NODISCARD _CONSTEXPR20 bool operator==(const _Vector_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Ptr == _Right._Ptr; + } + +#if _HAS_CXX20 + _NODISCARD constexpr strong_ordering operator<=>(const _Vector_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Unfancy(_Ptr) <=> _Unfancy(_Right._Ptr); + } +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + _NODISCARD bool operator!=(const _Vector_const_iterator& _Right) const noexcept { + return !(*this == _Right); + } + + _NODISCARD bool operator<(const _Vector_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Ptr < _Right._Ptr; + } + + _NODISCARD bool operator>(const _Vector_const_iterator& _Right) const noexcept { + return _Right < *this; + } + + _NODISCARD bool operator<=(const _Vector_const_iterator& _Right) const noexcept { + return !(_Right < *this); + } + + _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { + return !(*this < _Right); + } +#endif // !_HAS_CXX20 + + _CONSTEXPR20 void _Compat(const _Vector_const_iterator& _Right) const noexcept { + // test for compatible iterator pair +#if _ITERATOR_DEBUG_LEVEL == 0 + (void) _Right; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#endif // _ITERATOR_DEBUG_LEVEL == 0 + } + +#if _ITERATOR_DEBUG_LEVEL != 0 + friend _CONSTEXPR20 void _Verify_range( + const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { + _STL_VERIFY(_First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); + _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + using _Prevent_inheriting_unwrap = _Vector_const_iterator; + + _NODISCARD _CONSTEXPR20 const value_type* _Unwrapped() const noexcept { + return _Unfancy(_Ptr); + } + + _CONSTEXPR20 void _Seek_to(const value_type* _It) noexcept { + _Ptr = _Refancy<_Tptr>(const_cast(_It)); + } + + _Tptr _Ptr; // pointer to element in vector +}; + +#if _HAS_CXX20 +template +struct pointer_traits<_Vector_const_iterator<_Myvec>> { + using pointer = _Vector_const_iterator<_Myvec>; + using element_type = const typename pointer::value_type; // TRANSITION, VSO-1854115, omit typename + using difference_type = pointer::difference_type; + + _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + // A value-initialized iterator is in the domain of to_address. An invalidated end iterator for a vector with + // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose + // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an + // iterator. + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return _STD to_address(_Iter._Ptr); + } +}; +#endif // _HAS_CXX20 + +template +class _Vector_iterator : public _Vector_const_iterator<_Myvec> { +public: + using _Mybase = _Vector_const_iterator<_Myvec>; + +#ifdef __cpp_lib_concepts + using iterator_concept = contiguous_iterator_tag; +#endif // defined(__cpp_lib_concepts) + using iterator_category = random_access_iterator_tag; + using value_type = typename _Myvec::value_type; + using difference_type = typename _Myvec::difference_type; + using pointer = typename _Myvec::pointer; + using reference = value_type&; + + using _Mybase::_Mybase; + + _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { + return const_cast(_Mybase::operator*()); + } + + _NODISCARD _CONSTEXPR20 pointer operator->() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont, "can't dereference invalidated vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, + "can't dereference out of range vector iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return this->_Ptr; + } + + _CONSTEXPR20 _Vector_iterator& operator++() noexcept { + _Mybase::operator++(); + return *this; + } + + _CONSTEXPR20 _Vector_iterator operator++(int) noexcept { + _Vector_iterator _Tmp = *this; + _Mybase::operator++(); + return _Tmp; + } + + _CONSTEXPR20 _Vector_iterator& operator--() noexcept { + _Mybase::operator--(); + return *this; + } + + _CONSTEXPR20 _Vector_iterator operator--(int) noexcept { + _Vector_iterator _Tmp = *this; + _Mybase::operator--(); + return _Tmp; + } + + _CONSTEXPR20 _Vector_iterator& operator+=(const difference_type _Off) noexcept { + _Mybase::operator+=(_Off); + return *this; + } + + _NODISCARD _CONSTEXPR20 _Vector_iterator operator+(const difference_type _Off) const noexcept { + _Vector_iterator _Tmp = *this; + _Tmp += _Off; + return _Tmp; + } + + _NODISCARD_FRIEND _CONSTEXPR20 _Vector_iterator operator+( + const difference_type _Off, _Vector_iterator _Next) noexcept { + _Next += _Off; + return _Next; + } + + _CONSTEXPR20 _Vector_iterator& operator-=(const difference_type _Off) noexcept { + _Mybase::operator-=(_Off); + return *this; + } + + using _Mybase::operator-; + + _NODISCARD _CONSTEXPR20 _Vector_iterator operator-(const difference_type _Off) const noexcept { + _Vector_iterator _Tmp = *this; + _Tmp -= _Off; + return _Tmp; + } + + _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { + return const_cast(_Mybase::operator[](_Off)); + } + + using _Prevent_inheriting_unwrap = _Vector_iterator; + + _NODISCARD _CONSTEXPR20 value_type* _Unwrapped() const noexcept { + return _Unfancy(this->_Ptr); + } +}; + +#if _HAS_CXX20 +template +struct pointer_traits<_Vector_iterator<_Myvec>> { + using pointer = _Vector_iterator<_Myvec>; + using element_type = pointer::value_type; + using difference_type = pointer::difference_type; + + _NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + // A value-initialized iterator is in the domain of to_address. An invalidated end iterator for a vector with + // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose + // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an + // iterator. + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return _STD to_address(_Iter._Ptr); + } +}; +#endif // _HAS_CXX20 + +template +struct _Vec_iter_types { + using value_type = _Value_type; + using size_type = _Size_type; + using difference_type = _Difference_type; + using pointer = _Pointer; + using const_pointer = _Const_pointer; +}; + +struct _Value_init_tag { // tag to request value-initialization + explicit _Value_init_tag() = default; +}; + +template +class _Vector_val : public _Container_base { +public: + using value_type = typename _Val_types::value_type; + using size_type = typename _Val_types::size_type; + using difference_type = typename _Val_types::difference_type; + using pointer = typename _Val_types::pointer; + using const_pointer = typename _Val_types::const_pointer; + using reference = value_type&; + using const_reference = const value_type&; + + _CONSTEXPR20 _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} + + _CONSTEXPR20 _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept + : _Myfirst(_First), _Mylast(_Last), _Myend(_End) {} + + _CONSTEXPR20 void _Swap_val(_Vector_val& _Right) noexcept { + this->_Swap_proxy_and_iterators(_Right); + swap(_Myfirst, _Right._Myfirst); // intentional ADL + swap(_Mylast, _Right._Mylast); // intentional ADL + swap(_Myend, _Right._Myend); // intentional ADL + } + + _CONSTEXPR20 void _Take_contents(_Vector_val& _Right) noexcept { + this->_Swap_proxy_and_iterators(_Right); + _Myfirst = _Right._Myfirst; + _Mylast = _Right._Mylast; + _Myend = _Right._Myend; + + _Right._Myfirst = nullptr; + _Right._Mylast = nullptr; + _Right._Myend = nullptr; + } + + pointer _Myfirst; // pointer to beginning of array + pointer _Mylast; // pointer to current end of sequence + pointer _Myend; // pointer to end of array +}; + +template +constexpr auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { + // converts from a (potentially null) fancy pointer to a plain pointer + return _Ptr ? _STD addressof(*_Ptr) : nullptr; +} + +template +constexpr _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers + return _Ptr; +} + +_EXPORT_STD template > +class vector { // varying size array of values +private: + template + friend class _Vb_val; + friend _Tidy_guard; + + using _Alty = _Rebind_alloc_t<_Alloc, _Ty>; + using _Alty_traits = allocator_traits<_Alty>; + +public: + static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Ty, typename _Alloc::value_type>, + _MISMATCHED_ALLOCATOR_MESSAGE("vector", "T")); + static_assert(is_object_v<_Ty>, "The C++ Standard forbids containers of non-object types " + "because of [container.requirements]."); + + using value_type = _Ty; + using allocator_type = _Alloc; + using pointer = typename _Alty_traits::pointer; + using const_pointer = typename _Alty_traits::const_pointer; + using reference = _Ty&; + using const_reference = const _Ty&; + using size_type = typename _Alty_traits::size_type; + using difference_type = typename _Alty_traits::difference_type; + +private: +#ifdef _INSERT_VECTOR_ANNOTATION + _CONSTEXPR20 void _Create_annotation() const noexcept { + // Annotates the shadow memory of the valid range + auto& _My_data = _Mypair._Myval2; + _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Myend, _My_data._Mylast); + } + + _CONSTEXPR20 void _Remove_annotation() const noexcept { + // Removes the shadow memory annotation of the range + auto& _My_data = _Mypair._Myval2; + _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Myend); + } + + _CONSTEXPR20 void _Modify_annotation(const difference_type _Count) const noexcept { + // Extends/shrinks the annotated range by _Count + if (_Count == 0) { // nothing to do + // This also avoids calling _Apply_annotation() with null pointers + // when the vector has zero capacity, see GH-2464. + return; + } + + auto& _My_data = _Mypair._Myval2; + _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Mylast + _Count); + } + + static _CONSTEXPR20 void _Apply_annotation( + pointer _First_, pointer _End_, pointer _Old_last_, pointer _New_last_) noexcept { + _STL_INTERNAL_CHECK(_First_ != nullptr); + _STL_INTERNAL_CHECK(_End_ != nullptr); + _STL_INTERNAL_CHECK(_Old_last_ != nullptr); + _STL_INTERNAL_CHECK(_New_last_ != nullptr); + +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + return; + } +#endif // _HAS_CXX20 + + if (!_Asan_vector_should_annotate) { + return; + } + + const void* const _First = _STD _Unfancy(_First_); + const void* const _End = _STD _Unfancy(_End_); + const void* const _Old_last = _STD _Unfancy(_Old_last_); + const void* const _New_last = _STD _Unfancy(_New_last_); + if constexpr ((_Container_allocation_minimum_asan_alignment) >= _Asan_granularity) { + // old state: + // [_First, _Old_last) valid + // [_Old_last, _End) poison + // new state: + // [_First, _New_last) valid + // [_New_last, asan_aligned_after(_End)) poison + _CSTD __sanitizer_annotate_contiguous_container( + _First, _STD _Get_asan_aligned_after(_End), _Old_last, _New_last); + } else { + const auto _Aligned = _STD _Get_asan_aligned_first_end(_First, _End); + if (_Aligned._First == _Aligned._End) { + // The buffer does not end at least one shadow memory section; nothing to do. + return; + } + + const void* const _Old_fixed = _Aligned._Clamp_to_end(_Old_last); + const void* const _New_fixed = _Aligned._Clamp_to_end(_New_last); + + // old state: + // [_Aligned._First, _Old_fixed) valid + // [_Old_fixed, _Aligned._End) poison + // [_Aligned._End, _End) valid + // new state: + // [_Aligned._First, _New_fixed) valid + // [_New_fixed, _Aligned._End) poison + // [_Aligned._End, _End) valid + _CSTD __sanitizer_annotate_contiguous_container(_Aligned._First, _Aligned._End, _Old_fixed, _New_fixed); + } + } + + class _NODISCARD _Asan_extend_guard { + public: + _Asan_extend_guard(const _Asan_extend_guard&) = delete; + _Asan_extend_guard& operator=(const _Asan_extend_guard&) = delete; + + constexpr explicit _Asan_extend_guard(vector* _Myvec_, size_type _Target_size_) noexcept + : _Myvec(_Myvec_), _Target_size(_Target_size_) { + _STL_INTERNAL_CHECK(_Myvec != nullptr); + auto& _My_data = _Myvec->_Mypair._Myval2; + _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Myfirst + _Target_size); + } + + _CONSTEXPR20 ~_Asan_extend_guard() { + if (!_Myvec) { // Operation succeeded, no modification to the shadow memory required. + return; + } + + // Shrinks the shadow memory to the current size of the vector. + auto& _My_data = _Myvec->_Mypair._Myval2; + _Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Myfirst + _Target_size, _My_data._Mylast); + } + + _CONSTEXPR20 void _Release() noexcept { + _Myvec = nullptr; + } + + private: + vector* _Myvec; + size_type _Target_size; + }; + + class _NODISCARD _Asan_create_guard { + public: + _Asan_create_guard(const _Asan_create_guard&) = delete; + _Asan_create_guard& operator=(const _Asan_create_guard&) = delete; + + constexpr explicit _Asan_create_guard(const vector& _Myvec_) noexcept : _Myvec(_Myvec_) {} + + _CONSTEXPR20 ~_Asan_create_guard() { + _Myvec._Create_annotation(); + } + + private: + const vector& _Myvec; + }; + +#define _ASAN_VECTOR_MODIFY(n) _Modify_annotation((n)) +#define _ASAN_VECTOR_REMOVE _Remove_annotation() +#define _ASAN_VECTOR_CREATE _Create_annotation() +#define _ASAN_VECTOR_CREATE_GUARD _Asan_create_guard _Annotator(*this) +#define _ASAN_VECTOR_EXTEND_GUARD(n) _Asan_extend_guard _Annotator(this, (n)) +#define _ASAN_VECTOR_RELEASE_GUARD _Annotator._Release() +#else // ^^^ _INSERT_VECTOR_ANNOTATION / !_INSERT_VECTOR_ANNOTATION vvv +#define _ASAN_VECTOR_MODIFY(n) +#define _ASAN_VECTOR_REMOVE +#define _ASAN_VECTOR_CREATE +#define _ASAN_VECTOR_CREATE_GUARD +#define _ASAN_VECTOR_EXTEND_GUARD(n) +#define _ASAN_VECTOR_RELEASE_GUARD +#endif // !_INSERT_VECTOR_ANNOTATION + + using _Scary_val = _Vector_val, _Simple_types<_Ty>, + _Vec_iter_types<_Ty, size_type, difference_type, pointer, const_pointer>>>; + +public: + using iterator = _Vector_iterator<_Scary_val>; + using const_iterator = _Vector_const_iterator<_Scary_val>; + using reverse_iterator = _STD reverse_iterator; + using const_reverse_iterator = _STD reverse_iterator; + + _CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Alty>) : _Mypair(_Zero_then_variadic_args_t{}) { + _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); + } + + _CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); + } + + _CONSTEXPR20 explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Construct_n(_Count); + } + + _CONSTEXPR20 vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Construct_n(_Count, _Val); + } + + template , int> = 0> + _CONSTEXPR20 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_First); + auto _ULast = _Get_unwrapped(_Last); + if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { + const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); +#ifdef __cpp_lib_concepts + } else if constexpr (forward_iterator<_Iter>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); +#endif // defined(__cpp_lib_concepts) + } else { + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); + _Tidy_guard _Guard{this}; + + _Append_uncounted_range(_STD move(_UFirst), _STD move(_ULast)); + + _Guard._Target = nullptr; + _Proxy._Release(); + } + } + + _CONSTEXPR20 vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + _Construct_n(_Convert_size(_Ilist.size()), _Ilist.begin(), _Ilist.end()); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range<_Ty> _Rng> + constexpr vector(from_range_t, _Rng&& _Range, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + if constexpr (_RANGES sized_range<_Rng> || _RANGES forward_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Construct_n(_Count, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } else { + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); + _Tidy_guard _Guard{this}; + + _Append_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + + _Guard._Target = nullptr; + _Proxy._Release(); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 vector(const vector& _Right) + : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { + const auto& _Right_data = _Right._Mypair._Myval2; + const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); + _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); + } + + _CONSTEXPR20 vector(const vector& _Right, const _Identity_t<_Alloc>& _Al) + : _Mypair(_One_then_variadic_args_t{}, _Al) { + const auto& _Right_data = _Right._Mypair._Myval2; + const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); + _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); + } + + _CONSTEXPR20 vector(vector&& _Right) noexcept + : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), + _STD exchange(_Right._Mypair._Myval2._Myfirst, nullptr), + _STD exchange(_Right._Mypair._Myval2._Mylast, nullptr), + _STD exchange(_Right._Mypair._Myval2._Myend, nullptr)) { + _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); + _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); + } + + _CONSTEXPR20 vector(vector&& _Right, const _Identity_t<_Alloc>& _Al_) noexcept( + _Alty_traits::is_always_equal::value) // strengthened + : _Mypair(_One_then_variadic_args_t{}, _Al_) { + _Alty& _Al = _Getal(); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al); + auto& _My_data = _Mypair._Myval2; + auto& _Right_data = _Right._Mypair._Myval2; + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); + + if constexpr (!_Alty_traits::is_always_equal::value) { + if (_Al != _Right._Getal()) { + const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); + if (_Count != 0) { + _Buy_raw(_Count); + _Tidy_guard _Guard{this}; + _My_data._Mylast = + _Uninitialized_move(_Right_data._Myfirst, _Right_data._Mylast, _My_data._Myfirst, _Al); + + _ASAN_VECTOR_CREATE; + _Guard._Target = nullptr; + } + _Proxy._Release(); + return; + } + } + + _My_data._Take_contents(_Right_data); + _Proxy._Release(); + } + + _CONSTEXPR20 vector& operator=(vector&& _Right) noexcept( + _Choose_pocma_v<_Alty> != _Pocma_values::_No_propagate_allocators) { + if (this == _STD addressof(_Right)) { + return *this; + } + + _Alty& _Al = _Getal(); + _Alty& _Right_al = _Right._Getal(); + constexpr auto _Pocma_val = _Choose_pocma_v<_Alty>; + if constexpr (_Pocma_val == _Pocma_values::_No_propagate_allocators) { + if (_Al != _Right_al) { + _Move_assign_unequal_alloc(_Right); + return *this; + } + } + + _Tidy(); +#if _ITERATOR_DEBUG_LEVEL != 0 + if constexpr (_Pocma_val == _Pocma_values::_Propagate_allocators) { + if (_Al != _Right_al) { + // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 + _Mypair._Myval2._Reload_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al), _GET_PROXY_ALLOCATOR(_Alty, _Right_al)); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + _Pocma(_Al, _Right_al); + _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); + return *this; + } + + _CONSTEXPR20 ~vector() noexcept { + _Tidy(); +#if _ITERATOR_DEBUG_LEVEL != 0 + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); + _Delete_plain_internal(_Alproxy, _STD exchange(_Mypair._Myval2._Myproxy, nullptr)); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + } + +private: + template + _CONSTEXPR20 _Ty& _Emplace_one_at_back(_Valty&&... _Val) { + // insert by perfectly forwarding into element at end, provide strong guarantee + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + + if (_Mylast != _My_data._Myend) { + return _Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...); + } + + return *_Emplace_reallocate(_Mylast, _STD forward<_Valty>(_Val)...); + } + + template + _CONSTEXPR20 _Ty& _Emplace_back_with_unused_capacity(_Valty&&... _Val) { + // insert by perfectly forwarding into element at end, provide strong guarantee + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + _STL_INTERNAL_CHECK(_Mylast != _My_data._Myend); // check that we have unused capacity + if constexpr (conjunction_v, + _Uses_default_construct<_Alloc, _Ty*, _Valty...>>) { + _ASAN_VECTOR_MODIFY(1); + _Construct_in_place(*_Mylast, _STD forward<_Valty>(_Val)...); + } else { + _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Mylast - _My_data._Myfirst) + 1); + _Alty_traits::construct(_Getal(), _Unfancy(_Mylast), _STD forward<_Valty>(_Val)...); + _ASAN_VECTOR_RELEASE_GUARD; + } + + _Orphan_range(_Mylast, _Mylast); + _Ty& _Result = *_Mylast; + ++_Mylast; + + return _Result; + } + + template + _CONSTEXPR20 pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { + // reallocate and insert by perfectly forwarding _Val at _Whereptr + _Alty& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + _STL_INTERNAL_CHECK(_Mylast == _My_data._Myend); // check that we have no unused capacity + + const auto _Whereoff = static_cast(_Whereptr - _Myfirst); + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + + if (_Oldsize == max_size()) { + _Xlength(); + } + + const size_type _Newsize = _Oldsize + 1; + size_type _Newcapacity = _Calculate_growth(_Newsize); + + const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Constructed_last = _Newvec + _Whereoff + 1; + pointer _Constructed_first = _Constructed_last; + + _TRY_BEGIN + _Alty_traits::construct(_Al, _Unfancy(_Newvec + _Whereoff), _STD forward<_Valty>(_Val)...); + _Constructed_first = _Newvec + _Whereoff; + + if (_Whereptr == _Mylast) { // at back, provide strong guarantee + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); + } + } else { // provide basic guarantee + _Uninitialized_move(_Myfirst, _Whereptr, _Newvec, _Al); + _Constructed_first = _Newvec; + _Uninitialized_move(_Whereptr, _Mylast, _Newvec + _Whereoff + 1, _Al); + } + _CATCH_ALL + _Destroy_range(_Constructed_first, _Constructed_last, _Al); + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Newsize, _Newcapacity); + return _Newvec + _Whereoff; + } + +public: + template + _CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) { + // insert by perfectly forwarding into element at end, provide strong guarantee + _Ty& _Result = _Emplace_one_at_back(_STD forward<_Valty>(_Val)...); +#if _HAS_CXX17 + return _Result; +#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv + (void) _Result; +#endif // _HAS_CXX17 + } + + _CONSTEXPR20 void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee + _Emplace_one_at_back(_Val); + } + + _CONSTEXPR20 void push_back(_Ty&& _Val) { + // insert by moving into element at end, provide strong guarantee + _Emplace_one_at_back(_STD move(_Val)); + } + +private: + template + _CONSTEXPR20 void _Append_uncounted_range(_Iter _First, const _Sent _Last) { + // insert range [_First, _Last) at end + + // For one-at-back, provide strong guarantee. + // Otherwise, provide basic guarantee (despite N4950 [vector.modifiers]/2). + // Performance note: except for one-at-back, _Emplace_one_at_back()'s strong guarantee is unnecessary here. + + for (; _First != _Last; ++_First) { + _Emplace_one_at_back(*_First); + } + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template + _CONSTEXPR20 void _Append_counted_range(_Iter _First, const size_type _Count) { + // insert counted range _First + [0, _Count) at end + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + + const pointer _Oldfirst = _My_data._Myfirst; + const pointer _Oldlast = _Mylast; + const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); + + if (_Count == 0) { // nothing to do, avoid invalidating iterators + } else if (_Count > _Unused_capacity) { // reallocate + const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); + + if (_Count > max_size() - _Oldsize) { + _Xlength(); + } + + const size_type _Newsize = _Oldsize + _Count; + size_type _Newcapacity = _Calculate_growth(_Newsize); + + const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Constructed_last = _Newvec + _Oldsize + _Count; + pointer _Constructed_first = _Constructed_last; + + _TRY_BEGIN + _Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Oldsize, _Al); + _Constructed_first = _Newvec + _Oldsize; + + if (_Count == 1) { // one at back, provide strong guarantee + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); + } + } else { // provide basic guarantee + _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); + } + _CATCH_ALL + _Destroy_range(_Constructed_first, _Constructed_last, _Al); + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Newsize, _Newcapacity); + } else { // Provide the strong guarantee. + // Performance note: except for one-at-back, the strong guarantee is unnecessary here. + + _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _Oldfirst) + _Count); + _Mylast = _Uninitialized_copy_n(_STD move(_First), _Count, _Oldlast, _Al); + _ASAN_VECTOR_RELEASE_GUARD; + + _Orphan_range(_Oldlast, _Oldlast); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + +public: +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range<_Ty> _Rng> + constexpr void append_range(_Rng&& _Range) { + if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Append_counted_range(_RANGES _Ubegin(_Range), _Count); + } else { + _Append_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + template + _CONSTEXPR20 iterator emplace(const_iterator _Where, _Valty&&... _Val) { + // insert by perfectly forwarding _Val at _Where + const pointer _Whereptr = _Where._Ptr; + auto& _My_data = _Mypair._Myval2; + const pointer _Oldlast = _My_data._Mylast; +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Oldlast >= _Whereptr, + "vector emplace iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + if (_Oldlast != _My_data._Myend) { + if (_Whereptr == _Oldlast) { // at back, provide strong guarantee + _Emplace_back_with_unused_capacity(_STD forward<_Valty>(_Val)...); + } else { + auto& _Al = _Getal(); + _Alloc_temporary2<_Alty> _Obj(_Al, _STD forward<_Valty>(_Val)...); // handle aliasing + // after constructing _Obj, provide basic guarantee + _Orphan_range(_Whereptr, _Oldlast); + _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _My_data._Myfirst) + 1); + _Alty_traits::construct(_Al, _Unfancy(_Oldlast), _STD move(_Oldlast[-1])); + _ASAN_VECTOR_RELEASE_GUARD; + ++_My_data._Mylast; + _Move_backward_unchecked(_Whereptr, _Oldlast - 1, _Oldlast); + *_Whereptr = _STD move(_Obj._Get_value()); + } + + return _Make_iterator(_Whereptr); + } + + return _Make_iterator(_Emplace_reallocate(_Whereptr, _STD forward<_Valty>(_Val)...)); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where + return emplace(_Where, _Val); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where + return emplace(_Where, _STD move(_Val)); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { + // insert _Count * _Val at _Where + const pointer _Whereptr = _Where._Ptr; + + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + + const pointer _Oldfirst = _My_data._Myfirst; + const pointer _Oldlast = _Mylast; +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, + "vector insert iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); + const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); + const bool _One_at_back = _Count == 1 && _Whereptr == _Oldlast; + if (_Count == 0) { // nothing to do, avoid invalidating iterators + } else if (_Count > _Unused_capacity) { // reallocate + const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); + + if (_Count > max_size() - _Oldsize) { + _Xlength(); + } + + const size_type _Newsize = _Oldsize + _Count; + size_type _Newcapacity = _Calculate_growth(_Newsize); + + const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Constructed_last = _Newvec + _Whereoff + _Count; + pointer _Constructed_first = _Constructed_last; + + _TRY_BEGIN + _Uninitialized_fill_n(_Newvec + _Whereoff, _Count, _Val, _Al); + _Constructed_first = _Newvec + _Whereoff; + + if (_One_at_back) { // provide strong guarantee + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); + } + } else { // provide basic guarantee + _Uninitialized_move(_Oldfirst, _Whereptr, _Newvec, _Al); + _Constructed_first = _Newvec; + _Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al); + } + _CATCH_ALL + _Destroy_range(_Constructed_first, _Constructed_last, _Al); + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Newsize, _Newcapacity); + } else if (_One_at_back) { // provide strong guarantee + _Emplace_back_with_unused_capacity(_Val); + } else { // provide basic guarantee + const _Alloc_temporary2<_Alty> _Tmp_storage(_Al, _Val); // handle aliasing + const auto& _Tmp = _Tmp_storage._Get_value(); + const auto _Affected_elements = static_cast(_Oldlast - _Whereptr); + _Orphan_range(_Whereptr, _Oldlast); + + _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _My_data._Myfirst) + _Count); + if (_Count > _Affected_elements) { // new stuff spills off end + _Mylast = _Uninitialized_fill_n(_Oldlast, _Count - _Affected_elements, _Tmp, _Al); + _Mylast = _Uninitialized_move(_Whereptr, _Oldlast, _Mylast, _Al); + _STD fill(_Whereptr, _Oldlast, _Tmp); + } else { // new stuff can all be assigned + _Mylast = _Uninitialized_move(_Oldlast - _Count, _Oldlast, _Oldlast, _Al); + _Move_backward_unchecked(_Whereptr, _Oldlast - _Count, _Oldlast); + _STD fill_n(_Whereptr, _Count, _Tmp); + } + _ASAN_VECTOR_RELEASE_GUARD; + } + + return _Make_iterator_offset(_Whereoff); + } + +private: + template + _CONSTEXPR20 void _Insert_uncounted_range(const_iterator _Where, _Iter _First, _Sent _Last) { + // insert range [_First, _Last) at _Where + if (_First == _Last) { + return; // nothing to do, avoid invalidating iterators + } + + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + const auto _Whereoff = static_cast(_Where._Ptr - _Myfirst); + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + + _Append_uncounted_range(_STD move(_First), _STD move(_Last)); + + _Orphan_range(_Myfirst + _Whereoff, _Myfirst + _Oldsize); + + _STD rotate(_Myfirst + _Whereoff, _Myfirst + _Oldsize, _Mylast); + } + + template + _CONSTEXPR20 void _Insert_counted_range(const_iterator _Where, _Iter _First, const size_type _Count) { + // insert counted range _First + [0, _Count) at _Where + const pointer _Whereptr = _Where._Ptr; + + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + + const pointer _Oldfirst = _My_data._Myfirst; + const pointer _Oldlast = _Mylast; + const auto _Unused_capacity = static_cast(_My_data._Myend - _Oldlast); + + if (_Count == 0) { // nothing to do, avoid invalidating iterators + } else if (_Count > _Unused_capacity) { // reallocate + const auto _Oldsize = static_cast(_Oldlast - _Oldfirst); + + if (_Count > max_size() - _Oldsize) { + _Xlength(); + } + + const size_type _Newsize = _Oldsize + _Count; + size_type _Newcapacity = _Calculate_growth(_Newsize); + + const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); + const pointer _Constructed_last = _Newvec + _Whereoff + _Count; + pointer _Constructed_first = _Constructed_last; + + _TRY_BEGIN + _Uninitialized_copy_n(_STD move(_First), _Count, _Newvec + _Whereoff, _Al); + _Constructed_first = _Newvec + _Whereoff; + + if (_Count == 1 && _Whereptr == _Oldlast) { // one at back, provide strong guarantee + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Oldfirst, _Oldlast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Oldfirst, _Oldlast, _Newvec, _Al); + } + } else { // provide basic guarantee + _Uninitialized_move(_Oldfirst, _Whereptr, _Newvec, _Al); + _Constructed_first = _Newvec; + _Uninitialized_move(_Whereptr, _Oldlast, _Newvec + _Whereoff + _Count, _Al); + } + _CATCH_ALL + _Destroy_range(_Constructed_first, _Constructed_last, _Al); + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Newsize, _Newcapacity); + } else { // Attempt to provide the strong guarantee for EmplaceConstructible failure. + // If we encounter copy/move construction/assignment failure, provide the basic guarantee. + // (For one-at-back, this provides the strong guarantee.) + + const auto _Affected_elements = static_cast(_Oldlast - _Whereptr); + + _ASAN_VECTOR_EXTEND_GUARD(static_cast(_Oldlast - _Oldfirst) + _Count); + if (_Count < _Affected_elements) { // some affected elements must be assigned + _Mylast = _Uninitialized_move(_Oldlast - _Count, _Oldlast, _Oldlast, _Al); + _Move_backward_unchecked(_Whereptr, _Oldlast - _Count, _Oldlast); + _Destroy_range(_Whereptr, _Whereptr + _Count, _Al); + + _TRY_BEGIN + _Uninitialized_copy_n(_STD move(_First), _Count, _Whereptr, _Al); + _CATCH_ALL + // glue the broken pieces back together + + _TRY_BEGIN + _Uninitialized_move(_Whereptr + _Count, _Whereptr + 2 * _Count, _Whereptr, _Al); + _CATCH_ALL + // vaporize the detached piece + _Orphan_range(_Whereptr, _Oldlast); + _Destroy_range(_Whereptr + _Count, _Mylast, _Al); + _Mylast = _Whereptr; + _RERAISE; + _CATCH_END + + _STD _Move_unchecked(_Whereptr + 2 * _Count, _Mylast, _Whereptr + _Count); + _Destroy_range(_Oldlast, _Mylast, _Al); + _Mylast = _Oldlast; + _RERAISE; + _CATCH_END + } else { // affected elements don't overlap before/after + const pointer _Relocated = _Whereptr + _Count; + _Mylast = _Uninitialized_move(_Whereptr, _Oldlast, _Relocated, _Al); + _Destroy_range(_Whereptr, _Oldlast, _Al); + + _TRY_BEGIN + _Uninitialized_copy_n(_STD move(_First), _Count, _Whereptr, _Al); + _CATCH_ALL + // glue the broken pieces back together + + _TRY_BEGIN + _Uninitialized_move(_Relocated, _Mylast, _Whereptr, _Al); + _CATCH_ALL + // vaporize the detached piece + _Orphan_range(_Whereptr, _Oldlast); + _Destroy_range(_Relocated, _Mylast, _Al); + _Mylast = _Whereptr; + _RERAISE; + _CATCH_END + + _Destroy_range(_Relocated, _Mylast, _Al); + _Mylast = _Oldlast; + _RERAISE; + _CATCH_END + } + + _Orphan_range(_Whereptr, _Oldlast); + _ASAN_VECTOR_RELEASE_GUARD; + } + } + +public: + template , int> = 0> + _CONSTEXPR20 iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + const pointer _Whereptr = _Where._Ptr; + auto& _My_data = _Mypair._Myval2; + const pointer _Oldfirst = _My_data._Myfirst; +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, + "vector insert iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_First); + auto _ULast = _Get_unwrapped(_Last); + const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); + if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { + const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Insert_counted_range(_Where, _UFirst, _Count); +#ifdef __cpp_lib_concepts + } else if constexpr (forward_iterator<_Iter>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Insert_counted_range(_Where, _UFirst, _Count); +#endif // defined(__cpp_lib_concepts) + } else { + _Insert_uncounted_range(_Where, _UFirst, _ULast); + } + return _Make_iterator_offset(_Whereoff); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range<_Ty> _Rng> + constexpr iterator insert_range(const_iterator _Where, _Rng&& _Range) { + const pointer _Whereptr = _Where._Ptr; + auto& _My_data = _Mypair._Myval2; + const pointer _Oldfirst = _My_data._Myfirst; +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, + "vector insert_range iterator out-of-range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); + + if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Insert_counted_range(_Where, _RANGES _Ubegin(_Range), _Count); + } else { + _Insert_uncounted_range(_Where, _RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + return _Make_iterator_offset(_Whereoff); + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { + const pointer _Whereptr = _Where._Ptr; + auto& _My_data = _Mypair._Myval2; + const pointer _Oldfirst = _My_data._Myfirst; +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, + "vector insert iterator out-of-range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); + + const auto _Count = _Convert_size(_Ilist.size()); + _Insert_counted_range(_Where, _Ilist.begin(), _Count); + return _Make_iterator_offset(_Whereoff); + } + + _CONSTEXPR20 void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + // assign _Newsize * _Val + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + +#if _ITERATOR_DEBUG_LEVEL == 2 +#if _HAS_CXX20 + if (!_STD is_constant_evaluated()) +#endif // _HAS_CXX20 + { + const auto _Valptr = _STD addressof(_Val); + _STL_VERIFY(!(_Unfancy(_Myfirst) <= _Valptr && _Valptr < _Unfancy(_Mylast)), + "assignment value cannot be a reference into the container"); + } +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + constexpr bool _Nothrow_construct = + conjunction_v, _Uses_default_construct<_Alloc, _Ty*, const _Ty&>>; + + _My_data._Orphan_all(); + const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { // reallocate + _Clear_and_reserve_geometric(_Newsize); + if constexpr (_Nothrow_construct) { + _Mylast = _Uninitialized_fill_n(_Myfirst, _Newsize, _Val, _Al); + _ASAN_VECTOR_CREATE; + } else { + _ASAN_VECTOR_CREATE_GUARD; + _Mylast = _Uninitialized_fill_n(_Myfirst, _Newsize, _Val, _Al); + } + + return; + } + + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + if (_Newsize > _Oldsize) { + _STD fill(_Myfirst, _Mylast, _Val); + if constexpr (_Nothrow_construct) { + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Uninitialized_fill_n(_Mylast, _Newsize - _Oldsize, _Val, _Al); + } else { + _ASAN_VECTOR_EXTEND_GUARD(_Newsize); + _Mylast = _Uninitialized_fill_n(_Mylast, _Newsize - _Oldsize, _Val, _Al); + _ASAN_VECTOR_RELEASE_GUARD; + } + } else { + const pointer _Newlast = _Myfirst + _Newsize; + _STD fill(_Myfirst, _Newlast, _Val); + _Destroy_range(_Newlast, _Mylast, _Al); + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Newlast; + } + } + +private: + template + _CONSTEXPR20 void _Assign_uncounted_range(_Iter _First, _Sent _Last) { + // assign unknown number of elements from [_First, _Last) + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + _My_data._Orphan_all(); + + pointer _Next = _Myfirst; + for (; _First != _Last && _Next != _Mylast; ++_First, (void) ++_Next) { + *_Next = *_First; + } + + // Code size optimization: we've exhausted only the source, only the dest, or both. + // If we've exhausted only the source: we Trim, then Append does nothing. + // If we've exhausted only the dest: Trim does nothing, then we Append. + // If we've exhausted both: Trim does nothing, then Append does nothing. + + // Trim. + _Destroy_range(_Next, _Mylast, _Getal()); + _ASAN_VECTOR_MODIFY(static_cast(_Next - _Mylast)); // negative when destroying elements + _Mylast = _Next; + + _Append_uncounted_range(_STD move(_First), _STD move(_Last)); + } + + template + _CONSTEXPR20 void _Assign_counted_range(_Iter _First, const size_type _Newsize) { + // assign elements from counted range _First + [0, _Newsize) + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + + constexpr bool _Nothrow_construct = conjunction_v>, + _Uses_default_construct<_Alloc, _Ty*, _Iter_ref_t<_Iter>>>; + + _My_data._Orphan_all(); + const auto _Oldcapacity = static_cast(_Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { + _Clear_and_reserve_geometric(_Newsize); + if constexpr (_Nothrow_construct) { + _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize, _Myfirst, _Al); + _ASAN_VECTOR_CREATE; + } else { + _ASAN_VECTOR_CREATE_GUARD; + _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize, _Myfirst, _Al); + } + return; + } + + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + if (_Newsize > _Oldsize) { + bool _Copied = false; + if constexpr (_Iter_copy_cat<_Iter, pointer>::_Bitcopy_assignable) { +#if _HAS_CXX20 + if (!_STD is_constant_evaluated()) +#endif // _HAS_CXX20 + { + _Copy_memmove_n(_First, static_cast(_Oldsize), _Myfirst); + _First += _Oldsize; + _Copied = true; + } + } + + if (!_Copied) { + for (auto _Mid = _Myfirst; _Mid != _Mylast; ++_Mid, (void) ++_First) { + *_Mid = *_First; + } + } + + if constexpr (_Nothrow_construct) { + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize - _Oldsize, _Mylast, _Al); + } else { + _ASAN_VECTOR_EXTEND_GUARD(_Newsize); + _Mylast = _Uninitialized_copy_n(_STD move(_First), _Newsize - _Oldsize, _Mylast, _Al); + _ASAN_VECTOR_RELEASE_GUARD; + } + } else { + const pointer _Newlast = _Myfirst + _Newsize; + _Copy_n_unchecked4(_STD move(_First), _Newsize, _Myfirst); + _Destroy_range(_Newlast, _Mylast, _Al); + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Newlast; + } + } + +public: + template , int> = 0> + _CONSTEXPR20 void assign(_Iter _First, _Iter _Last) { + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_First); + auto _ULast = _Get_unwrapped(_Last); + if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { + const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Assign_counted_range(_UFirst, _Count); +#ifdef __cpp_lib_concepts + } else if constexpr (forward_iterator<_Iter>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + _Assign_counted_range(_UFirst, _Count); +#endif // defined(__cpp_lib_concepts) + } else { + _Assign_uncounted_range(_UFirst, _ULast); + } + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range<_Ty> _Rng> + constexpr void assign_range(_Rng&& _Range) { + if constexpr (_RANGES sized_range<_Rng> || _RANGES forward_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); + } else { + _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 void assign(const initializer_list<_Ty> _Ilist) { + const auto _Count = _Convert_size(_Ilist.size()); + _Assign_counted_range(_Ilist.begin(), _Count); + } + + _CONSTEXPR20 vector& operator=(const vector& _Right) { + if (this == _STD addressof(_Right)) { + return *this; + } + + auto& _Al = _Getal(); + auto& _Right_al = _Right._Getal(); + if constexpr (_Choose_pocca_v<_Alty>) { + if (_Al != _Right_al) { + _Tidy(); + _Mypair._Myval2._Reload_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al), _GET_PROXY_ALLOCATOR(_Alty, _Right_al)); + } + } + + _Pocca(_Al, _Right_al); + auto& _Right_data = _Right._Mypair._Myval2; + _Assign_counted_range(_Right_data._Myfirst, static_cast(_Right_data._Mylast - _Right_data._Myfirst)); + + return *this; + } + + _CONSTEXPR20 vector& operator=(initializer_list<_Ty> _Ilist) { + const auto _Count = _Convert_size(_Ilist.size()); + _Assign_counted_range(_Ilist.begin(), _Count); + return *this; + } + +private: + template + _CONSTEXPR20 void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { + if (_Newsize > max_size()) { + _Xlength(); + } + + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + size_type _Newcapacity = _Calculate_growth(_Newsize); + + const pointer _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + const pointer _Appended_first = _Newvec + _Oldsize; + pointer _Appended_last = _Appended_first; + + _TRY_BEGIN + if constexpr (is_same_v<_Ty2, _Ty>) { + _Appended_last = _Uninitialized_fill_n(_Appended_first, _Newsize - _Oldsize, _Val, _Al); + } else { + _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Ty2, _Value_init_tag>); + _Appended_last = _Uninitialized_value_construct_n(_Appended_first, _Newsize - _Oldsize, _Al); + } + + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); + } + _CATCH_ALL + _Destroy_range(_Appended_first, _Appended_last, _Al); + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Newsize, _Newcapacity); + } + + template + _CONSTEXPR20 void _Resize(const size_type _Newsize, const _Ty2& _Val) { + // trim or append elements, provide strong guarantee + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + if (_Newsize < _Oldsize) { // trim + const pointer _Newlast = _Myfirst + _Newsize; + _Orphan_range(_Newlast, _Mylast); + _Destroy_range(_Newlast, _Mylast, _Al); + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Newlast; + return; + } + + if (_Newsize > _Oldsize) { // append + const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { // reallocate + _Resize_reallocate(_Newsize, _Val); + return; + } + + _ASAN_VECTOR_EXTEND_GUARD(_Newsize); + const pointer _Oldlast = _Mylast; + if constexpr (is_same_v<_Ty2, _Ty>) { + _Mylast = _Uninitialized_fill_n(_Oldlast, _Newsize - _Oldsize, _Val, _Al); + } else { + _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Ty2, _Value_init_tag>); + _Mylast = _Uninitialized_value_construct_n(_Oldlast, _Newsize - _Oldsize, _Al); + } + _ASAN_VECTOR_RELEASE_GUARD; + _Orphan_range(_Oldlast, _Oldlast); + } + + // if _Newsize == _Oldsize, do nothing; avoid invalidating iterators + } + +public: + _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { + // trim or append value-initialized elements, provide strong guarantee + _Resize(_Newsize, _Value_init_tag{}); + } + + _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + // trim or append copies of _Val, provide strong guarantee + _Resize(_Newsize, _Val); + } + +private: + enum class _Reallocation_policy { _At_least, _Exactly }; + + template <_Reallocation_policy _Policy> + _CONSTEXPR20 void _Reallocate(size_type& _Newcapacity) { + // set capacity to _Newcapacity (without geometric growth), provide strong guarantee + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + const auto _Size = static_cast(_Mylast - _Myfirst); + + pointer _Newvec; + if constexpr (_Policy == _Reallocation_policy::_At_least) { + _Newvec = _Allocate_at_least_helper(_Al, _Newcapacity); + } else { + _STL_INTERNAL_STATIC_ASSERT(_Policy == _Reallocation_policy::_Exactly); + _Newvec = _Al.allocate(_Newcapacity); + } + + _TRY_BEGIN + if constexpr (is_nothrow_move_constructible_v<_Ty> || !is_copy_constructible_v<_Ty>) { + _Uninitialized_move(_Myfirst, _Mylast, _Newvec, _Al); + } else { + _Uninitialized_copy(_Myfirst, _Mylast, _Newvec, _Al); + } + _CATCH_ALL + _Al.deallocate(_Newvec, _Newcapacity); + _RERAISE; + _CATCH_END + + _Change_array(_Newvec, _Size, _Newcapacity); + } + +#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + void _Check_all_orphaned_locked() const noexcept { + _Lockit _Lock(_LOCK_DEBUG); + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } + + _CONSTEXPR20 void _Check_all_orphaned() const noexcept { +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } else +#endif // _HAS_CXX20 + { + _Check_all_orphaned_locked(); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + + _CONSTEXPR20 void _Clear_and_reserve_geometric(const size_type _Newsize) { + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + +#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + _STL_INTERNAL_CHECK(_Newsize != 0); + _Check_all_orphaned(); +#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + + if (_Newsize > max_size()) { + _Xlength(); + } + + const size_type _Newcapacity = _Calculate_growth(_Newsize); + + if (_Myfirst) { // destroy and deallocate old array + _Destroy_range(_Myfirst, _Mylast, _Al); + _ASAN_VECTOR_REMOVE; + _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); + + _Myfirst = nullptr; + _Mylast = nullptr; + _Myend = nullptr; + } + + _Buy_raw(_Newcapacity); + } + +public: + _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW size_type _Newcapacity) { + // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee + if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks) + if (_Newcapacity > max_size()) { + _Xlength(); + } + + _Reallocate<_Reallocation_policy::_At_least>(_Newcapacity); + } + } + + _CONSTEXPR20 void shrink_to_fit() { // reduce capacity to size, provide strong guarantee + auto& _My_data = _Mypair._Myval2; + const pointer _Oldlast = _My_data._Mylast; + if (_Oldlast != _My_data._Myend) { // something to do + const pointer _Oldfirst = _My_data._Myfirst; + if (_Oldfirst == _Oldlast) { + _Tidy(); + } else { + size_type _Newcapacity = static_cast(_Oldlast - _Oldfirst); + _Reallocate<_Reallocation_policy::_Exactly>(_Newcapacity); + } + } + } + + _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + _Orphan_range(_Mylast - 1, _Mylast); + _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); + _ASAN_VECTOR_MODIFY(-1); + --_Mylast; + } + + _CONSTEXPR20 iterator erase(const_iterator _Where) noexcept( + is_nothrow_move_assignable_v) /* strengthened */ { + const pointer _Whereptr = _Where._Ptr; + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, + "vector erase iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + _Orphan_range(_Whereptr, _Mylast); + _STD _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); + _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); + _ASAN_VECTOR_MODIFY(-1); + --_Mylast; + return iterator(_Whereptr, _STD addressof(_My_data)); + } + + _CONSTEXPR20 iterator erase(const_iterator _First, const_iterator _Last) noexcept( + is_nothrow_move_assignable_v) /* strengthened */ { + const pointer _Firstptr = _First._Ptr; + const pointer _Lastptr = _Last._Ptr; + auto& _My_data = _Mypair._Myval2; + pointer& _Mylast = _My_data._Mylast; + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) + && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, + "vector erase iterator outside range"); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + if (_Firstptr != _Lastptr) { // something to do, invalidate iterators + _Orphan_range(_Firstptr, _Mylast); + + const pointer _Newlast = _STD _Move_unchecked(_Lastptr, _Mylast, _Firstptr); + _Destroy_range(_Newlast, _Mylast, _Getal()); + _ASAN_VECTOR_MODIFY(static_cast(_Newlast - _Mylast)); // negative when destroying elements + _Mylast = _Newlast; + } + + return iterator(_Firstptr, _STD addressof(_My_data)); + } + + _CONSTEXPR20 void clear() noexcept { // erase all + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + if (_Myfirst == _Mylast) { // already empty, nothing to do + // This is an optimization for debug mode: we can avoid taking the debug lock to invalidate iterators. + // Note that when clearing an empty vector, this will preserve past-the-end iterators, which is allowed by + // N4950 [sequence.reqmts]/54 "a.clear() [...] may invalidate the past-the-end iterator". + return; + } + + _My_data._Orphan_all(); + _Destroy_range(_Myfirst, _Mylast, _Getal()); + _ASAN_VECTOR_MODIFY(static_cast(_Myfirst - _Mylast)); // negative when destroying elements + _Mylast = _Myfirst; + } + + _CONSTEXPR20 void swap(vector& _Right) noexcept /* strengthened */ { + if (this != _STD addressof(_Right)) { + _Pocs(_Getal(), _Right._Getal()); + _Mypair._Myval2._Swap_val(_Right._Mypair._Myval2); + } + } + + _NODISCARD _CONSTEXPR20 _Ty* data() noexcept { + return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); + } + + _NODISCARD _CONSTEXPR20 const _Ty* data() const noexcept { + return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); + } + + _NODISCARD _CONSTEXPR20 iterator begin() noexcept { + auto& _My_data = _Mypair._Myval2; + return iterator(_My_data._Myfirst, _STD addressof(_My_data)); + } + + _NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept { + auto& _My_data = _Mypair._Myval2; + return const_iterator(_My_data._Myfirst, _STD addressof(_My_data)); + } + + _NODISCARD _CONSTEXPR20 iterator end() noexcept { + auto& _My_data = _Mypair._Myval2; + return iterator(_My_data._Mylast, _STD addressof(_My_data)); + } + + _NODISCARD _CONSTEXPR20 const_iterator end() const noexcept { + auto& _My_data = _Mypair._Myval2; + return const_iterator(_My_data._Mylast, _STD addressof(_My_data)); + } + + _NODISCARD _CONSTEXPR20 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + + _NODISCARD _CONSTEXPR20 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } + + _NODISCARD _CONSTEXPR20 const_iterator cbegin() const noexcept { + return begin(); + } + + _NODISCARD _CONSTEXPR20 const_iterator cend() const noexcept { + return end(); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { + return rbegin(); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator crend() const noexcept { + return rend(); + } + + _NODISCARD _CONSTEXPR20 pointer _Unchecked_begin() noexcept { + return _Mypair._Myval2._Myfirst; + } + + _NODISCARD _CONSTEXPR20 const_pointer _Unchecked_begin() const noexcept { + return _Mypair._Myval2._Myfirst; + } + + _NODISCARD _CONSTEXPR20 pointer _Unchecked_end() noexcept { + return _Mypair._Myval2._Mylast; + } + + _NODISCARD _CONSTEXPR20 const_pointer _Unchecked_end() const noexcept { + return _Mypair._Myval2._Mylast; + } + + _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { + auto& _My_data = _Mypair._Myval2; + return _My_data._Myfirst == _My_data._Mylast; + } + + _NODISCARD _CONSTEXPR20 size_type size() const noexcept { + auto& _My_data = _Mypair._Myval2; + return static_cast(_My_data._Mylast - _My_data._Myfirst); + } + + _NODISCARD _CONSTEXPR20 size_type max_size() const noexcept { + return (_STD min)( + static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); + } + + _NODISCARD _CONSTEXPR20 size_type capacity() const noexcept { + auto& _My_data = _Mypair._Myval2; + return static_cast(_My_data._Myend - _My_data._Myfirst); + } + + _NODISCARD _CONSTEXPR20 _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return _My_data._Myfirst[_Pos]; + } + + _NODISCARD _CONSTEXPR20 const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return _My_data._Myfirst[_Pos]; + } + + _NODISCARD _CONSTEXPR20 _Ty& at(const size_type _Pos) { + auto& _My_data = _Mypair._Myval2; + if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { + _Xrange(); + } + + return _My_data._Myfirst[_Pos]; + } + + _NODISCARD _CONSTEXPR20 const _Ty& at(const size_type _Pos) const { + auto& _My_data = _Mypair._Myval2; + if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { + _Xrange(); + } + + return _My_data._Myfirst[_Pos]; + } + + _NODISCARD _CONSTEXPR20 _Ty& front() noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *_My_data._Myfirst; + } + + _NODISCARD _CONSTEXPR20 const _Ty& front() const noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *_My_data._Myfirst; + } + + _NODISCARD _CONSTEXPR20 _Ty& back() noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return _My_data._Mylast[-1]; + } + + _NODISCARD _CONSTEXPR20 const _Ty& back() const noexcept /* strengthened */ { + auto& _My_data = _Mypair._Myval2; +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return _My_data._Mylast[-1]; + } + + _NODISCARD _CONSTEXPR20 allocator_type get_allocator() const noexcept { + return static_cast(_Getal()); + } + +private: + _CONSTEXPR20 size_type _Calculate_growth(const size_type _Newsize) const { + // given _Oldcapacity and _Newsize, calculate geometric growth + const size_type _Oldcapacity = capacity(); + const auto _Max = max_size(); + + if (_Oldcapacity > _Max - _Oldcapacity / 2) { + return _Max; // geometric growth would overflow + } + + const size_type _Geometric = _Oldcapacity + _Oldcapacity / 2; + + if (_Geometric < _Newsize) { + return _Newsize; // geometric growth would be insufficient + } + + return _Geometric; // geometric growth is sufficient + } + + _CONSTEXPR20 void _Buy_raw(size_type _Newcapacity) { + // allocate array with _Newcapacity elements + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + + _STL_INTERNAL_CHECK(!_Myfirst && !_Mylast && !_Myend); // check that *this is tidy + _STL_INTERNAL_CHECK(0 < _Newcapacity && _Newcapacity <= max_size()); + + const pointer _Newvec = _Allocate_at_least_helper(_Getal(), _Newcapacity); + _Myfirst = _Newvec; + _Mylast = _Newvec; + _Myend = _Newvec + _Newcapacity; + } + + _CONSTEXPR20 void _Buy_nonzero(const size_type _Newcapacity) { + // allocate array with _Newcapacity elements +#ifdef _ENABLE_STL_INTERNAL_CHECK + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + _STL_INTERNAL_CHECK(!_Myfirst && !_Mylast && !_Myend); // check that *this is tidy + _STL_INTERNAL_CHECK(0 < _Newcapacity); +#endif // _ENABLE_STL_INTERNAL_CHECK + + if (_Newcapacity > max_size()) { + _Xlength(); + } + + _Buy_raw(_Newcapacity); + } + + _CONSTEXPR20 void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { + // orphan all iterators, discard old array, acquire new array + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + + _My_data._Orphan_all(); + + if (_Myfirst) { // destroy and deallocate old array + _Destroy_range(_Myfirst, _Mylast, _Al); + _ASAN_VECTOR_REMOVE; + _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); + } + + _Myfirst = _Newvec; + _Mylast = _Newvec + _Newsize; + _Myend = _Newvec + _Newcapacity; + _ASAN_VECTOR_CREATE; + } + + _CONSTEXPR20 void _Tidy() noexcept { // free all storage + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + pointer& _Myend = _My_data._Myend; + + _My_data._Orphan_all(); + + if (_Myfirst) { // destroy and deallocate old array + _Destroy_range(_Myfirst, _Mylast, _Al); + _ASAN_VECTOR_REMOVE; + _Al.deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); + + _Myfirst = nullptr; + _Mylast = nullptr; + _Myend = nullptr; + } + } + + template + _CONSTEXPR20 void _Construct_n(_CRT_GUARDOVERFLOW const size_type _Count, _Valty&&... _Val) { + // Dispatches between the three sized constructions. + // 1-arg -> value-construction, e.g. vector(5) + // 2-arg -> fill, e.g. vector(5, "meow") + // 3-arg -> sized range construction, e.g. vector{"Hello", "Fluffy", "World"} + auto& _Al = _Getal(); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al); + auto& _My_data = _Mypair._Myval2; + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); + if (_Count != 0) { + _Buy_nonzero(_Count); + _Tidy_guard _Guard{this}; + if constexpr (sizeof...(_Val) == 0) { + _My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al); + } else if constexpr (sizeof...(_Val) == 1) { + _STL_INTERNAL_STATIC_ASSERT(is_same_v<_Valty..., const _Ty&>); + _My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val..., _Al); + } else if constexpr (sizeof...(_Val) == 2) { + _My_data._Mylast = _Uninitialized_copy(_STD forward<_Valty>(_Val)..., _My_data._Myfirst, _Al); + } else { + static_assert(_Always_false<_Ty>, "Should be unreachable"); + } + _ASAN_VECTOR_CREATE; + _Guard._Target = nullptr; + } + + _Proxy._Release(); + } + + _CONSTEXPR20 void _Move_assign_unequal_alloc(vector& _Right) { + auto& _Al = _Getal(); + auto& _My_data = _Mypair._Myval2; + auto& _Right_data = _Right._Mypair._Myval2; + + const pointer _First = _Right_data._Myfirst; + const pointer _Last = _Right_data._Mylast; + const auto _Newsize = static_cast(_Last - _First); + + pointer& _Myfirst = _My_data._Myfirst; + pointer& _Mylast = _My_data._Mylast; + + constexpr bool _Nothrow_construct = + conjunction_v, _Uses_default_construct<_Alloc, _Ty*, _Ty>>; + + _My_data._Orphan_all(); + const auto _Oldcapacity = static_cast(_My_data._Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { + _Clear_and_reserve_geometric(_Newsize); + if constexpr (_Nothrow_construct) { + _Mylast = _Uninitialized_move(_First, _Last, _Myfirst, _Al); + _ASAN_VECTOR_CREATE; + } else { + _ASAN_VECTOR_CREATE_GUARD; + _Mylast = _Uninitialized_move(_First, _Last, _Myfirst, _Al); + } + + return; + } + + const auto _Oldsize = static_cast(_Mylast - _Myfirst); + if (_Newsize > _Oldsize) { + const pointer _Mid = _First + _Oldsize; + _STD _Move_unchecked(_First, _Mid, _Myfirst); + + if constexpr (_Nothrow_construct) { + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Uninitialized_move(_Mid, _Last, _Mylast, _Al); + } else { + _ASAN_VECTOR_EXTEND_GUARD(_Newsize); + _Mylast = _Uninitialized_move(_Mid, _Last, _Mylast, _Al); + _ASAN_VECTOR_RELEASE_GUARD; + } + } else { + const pointer _Newlast = _Myfirst + _Newsize; + _STD _Move_unchecked(_First, _Last, _Myfirst); + _Destroy_range(_Newlast, _Mylast, _Al); + _ASAN_VECTOR_MODIFY(static_cast(_Newsize - _Oldsize)); + _Mylast = _Newlast; + } + } + + [[noreturn]] static void _Xlength() { + _Xlength_error("vector too long"); + } + + [[noreturn]] static void _Xrange() { + _Xout_of_range("invalid vector subscript"); + } + +#if _ITERATOR_DEBUG_LEVEL == 2 + _CONSTEXPR20 void _Orphan_range_unlocked(pointer _First, pointer _Last) const { + _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; + while (*_Pnext) { + const auto _Pnextptr = static_cast(**_Pnext)._Ptr; + const auto _Temp = *_Pnext; + if (_Pnextptr < _First || _Last < _Pnextptr) { // skip the iterator + _Pnext = &_Temp->_Mynextiter; + } else { // orphan the iterator + _Temp->_Myproxy = nullptr; + *_Pnext = _Temp->_Mynextiter; + } + } + } + + void _Orphan_range_locked(pointer _First, pointer _Last) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_First, _Last); + } + + _CONSTEXPR20 void _Orphan_range(pointer _First, pointer _Last) const { + // orphan iterators within specified (inclusive) range +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_First, _Last); + } else +#endif // _HAS_CXX20 + { + _Orphan_range_locked(_First, _Last); + } + } +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL != 2 vvv + _CONSTEXPR20 void _Orphan_range(pointer, pointer) const {} +#endif // _ITERATOR_DEBUG_LEVEL != 2 + + _NODISCARD _CONSTEXPR20 _Alty& _Getal() noexcept { + return _Mypair._Get_first(); + } + + _NODISCARD _CONSTEXPR20 const _Alty& _Getal() const noexcept { + return _Mypair._Get_first(); + } + + _NODISCARD _CONSTEXPR20 iterator _Make_iterator(const pointer _Ptr) noexcept { + return iterator(_Ptr, _STD addressof(_Mypair._Myval2)); + } + + _NODISCARD _CONSTEXPR20 iterator _Make_iterator_offset(const size_type _Offset) noexcept { + // return the iterator begin() + _Offset without a debugging check + auto& _My_data = _Mypair._Myval2; + return iterator(_My_data._Myfirst + _Offset, _STD addressof(_My_data)); + } + + _Compressed_pair<_Alty, _Scary_val> _Mypair; +}; + +#if _HAS_CXX17 +template >, + enable_if_t, _Is_allocator<_Alloc>>, int> = 0> +vector(_Iter, _Iter, _Alloc = _Alloc()) -> vector<_Iter_value_t<_Iter>, _Alloc>; +#endif // _HAS_CXX17 + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 +template <_RANGES input_range _Rng, class _Alloc = allocator<_RANGES range_value_t<_Rng>>, + enable_if_t<_Is_allocator<_Alloc>::value, int> = 0> +vector(from_range_t, _Rng&&, _Alloc = _Alloc()) -> vector<_RANGES range_value_t<_Rng>, _Alloc>; +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + +template +class vector; + +using _Vbase = unsigned int; // word type for vector representation + +_INLINE_VAR constexpr int _VBITS = 8 * sizeof(_Vbase); // at least CHAR_BITS bits per word + +_EXPORT_STD template +_NODISCARD _CONSTEXPR20 bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + if (_Left.size() != _Right.size()) { + return false; + } + + if constexpr (is_same_v<_Ty, bool>) { + return _STD equal( + _Left._Myvec._Unchecked_begin(), _Left._Myvec._Unchecked_end(), _Right._Myvec._Unchecked_begin()); + } else { + return _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); + } +} + +#if !_HAS_CXX20 +template +_NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + return !(_Left == _Right); +} +#endif // !_HAS_CXX20 + +// Optimize vector lexicographical comparisons. + +// There are several endianness/ordering issues to consider here. +// * Machine endianness is irrelevant. (That affects how an unsigned int is stored +// as a sequence of bytes. While all of our supported architectures are little-endian, +// that's irrelevant as long as we avoid reinterpreting unsigned int as a sequence of bytes.) +// * Appending bits to vector eventually appends words to its underlying storage. +// For example, vb[10] is stored within vb._Myvec[0], while vb[100] is stored within vb._Myvec[3]. +// This allows us to translate lexicographical comparisons from theoretical bits to physical words. +// * Unsigned integers are written and compared as big-endian (most significant bit first). +// For example, 0x10u > 0x07u. +// * However, vector packs bits into words as little-endian (least significant bit first). +// For example, vector{false, true, true, true} stores 0b0000'0000'0000'0000'0000'0000'0000'1110u. +// We could bit-reverse words before comparing, but we just need to find the least significant bit that differs. + +template +struct _Vbase_compare_three_way { + _NODISCARD constexpr _Ret operator()(const _Vbase _Left, const _Vbase _Right) const noexcept { + const _Vbase _Differing_bits = _Left ^ _Right; + + if (_Differing_bits == 0) { // improves _Countr_zero codegen below +#ifdef __cpp_lib_concepts + return strong_ordering::equal; +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv + return 0; +#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ + } + + const int _Bit_index = _Countr_zero(_Differing_bits); // number of least significant bits that match + _STL_INTERNAL_CHECK(_Bit_index < _VBITS); // because we return early for equality + + const _Vbase _Mask = _Vbase{1} << _Bit_index; // selects the least significant bit that differs + + // Instead of comparing (_Left & _Mask) to (_Right & _Mask), we know that exactly one side will be zero. +#ifdef __cpp_lib_concepts + return (_Left & _Mask) == 0 ? strong_ordering::less : strong_ordering::greater; +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv + return (_Left & _Mask) == 0 ? -1 : 1; +#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ + } +}; + +#ifdef __cpp_lib_concepts +_EXPORT_STD template +_NODISCARD constexpr _Synth_three_way_result<_Ty> operator<=>( + const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + if constexpr (is_same_v<_Ty, bool>) { + // This optimization works because vector "trims" its underlying storage by zeroing out unused bits. + const auto _Min_word_size = (_STD min)(_Left._Myvec.size(), _Right._Myvec.size()); + const auto _Left_words = _Left._Myvec._Unchecked_begin(); + const auto _Right_words = _Right._Myvec._Unchecked_begin(); + + using _Comp = _Vbase_compare_three_way; + + const strong_ordering _Word_comparison = _STD lexicographical_compare_three_way( + _Left_words, _Left_words + _Min_word_size, _Right_words, _Right_words + _Min_word_size, _Comp{}); + + if (_Word_comparison != 0) { + return _Word_comparison; + } + + return _Left.size() <=> _Right.size(); + } else { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end(), + _Right._Unchecked_begin(), _Right._Unchecked_end(), _Synth_three_way{}); + } +} +#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv +template +_NODISCARD _CONSTEXPR20 bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + if constexpr (is_same_v<_Ty, bool>) { + // This optimization works because vector "trims" its underlying storage by zeroing out unused bits. + auto _First = _Left._Myvec._Unchecked_begin(); + auto _Other = _Right._Myvec._Unchecked_begin(); + + const auto _Last = _First + (_STD min)(_Left._Myvec.size(), _Right._Myvec.size()); + + for (; _First != _Last; ++_First, (void) ++_Other) { + using _Comp = _Vbase_compare_three_way; + const auto _Result = _Comp{}(*_First, *_Other); + + if (_Result < 0) { + return true; + } else if (_Result > 0) { + return false; + } + } + + return _Left.size() < _Right.size(); + } else { + return _STD lexicographical_compare( + _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); + } +} + +template +_NODISCARD _CONSTEXPR20 bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + return _Right < _Left; +} + +template +_NODISCARD _CONSTEXPR20 bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + return !(_Right < _Left); +} + +template +_NODISCARD _CONSTEXPR20 bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + return !(_Left < _Right); +} +#endif // ^^^ !defined(__cpp_lib_concepts) ^^^ + +_EXPORT_STD template +_CONSTEXPR20 void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { + _Left.swap(_Right); +} + +#if _HAS_CXX20 +_EXPORT_STD template +constexpr vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { + return _Erase_remove(_Cont, _Val); +} + +_EXPORT_STD template +constexpr vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { + return _Erase_remove_if(_Cont, _Pass_fn(_Pred)); +} +#endif // _HAS_CXX20 + +template +struct _Wrap_alloc { // TRANSITION, ABI compat, preserves symbol names of vector::iterator + using _Alloc = _Alloc0; +}; + +template +class _Vb_iter_base : public _Iterator_base { + // store information common to reference and iterators +public: + using _Alvbase = typename _Alvbase_wrapped::_Alloc; + using _Size_type = typename allocator_traits<_Alvbase>::size_type; + using _Difference_type = typename allocator_traits<_Alvbase>::difference_type; + using _Mycont = vector>; + + static constexpr _Difference_type _VBITS_DIFF = _VBITS; + + _CONSTEXPR20 _Vb_iter_base() = default; + + _CONSTEXPR20 _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept + : _Myptr(_Ptr), _Myoff(_Off) { + this->_Adopt(_Mypvbool); + } + + _CONSTEXPR20 void _Advance(_Size_type _Off) noexcept { + _Myoff += _Off; + _Myptr += _Myoff / _VBITS; + _Myoff %= _VBITS; + } + +#if _ITERATOR_DEBUG_LEVEL != 0 + _CONSTEXPR20 _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { + return static_cast<_Difference_type>(_VBITS_DIFF * (_Myptr - _Cont->_Myvec.data()) + _Myoff); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + const _Vbase* _Myptr = nullptr; + _Size_type _Myoff = 0; +}; + +template +class _Vb_reference : public _Vb_iter_base<_Alvbase_wrapped> { + // reference to a bit within a base word +private: + using _Mybase = _Vb_iter_base<_Alvbase_wrapped>; + using _Mycont = typename _Mybase::_Mycont; + using _Difference_type = typename _Mybase::_Difference_type; + + // TRANSITION, ABI: non-trivial constructor + _CONSTEXPR20 _Vb_reference() = default; + +public: + _CONSTEXPR20 _Vb_reference(const _Vb_reference&) = default; + + _CONSTEXPR20 _Vb_reference(const _Mybase& _Right) noexcept + : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} + + _CONSTEXPR20 _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { + return *this = static_cast(_Right); + } + + _CONSTEXPR20 _Vb_reference& operator=(bool _Val) noexcept { + if (_Val) { + *const_cast<_Vbase*>(_Getptr()) |= _Mask(); + } else { + *const_cast<_Vbase*>(_Getptr()) &= ~_Mask(); + } + + return *this; + } + +#if _HAS_CXX23 + constexpr const _Vb_reference& operator=(bool _Val) const noexcept { + if (_Val) { + *const_cast<_Vbase*>(_Getptr()) |= _Mask(); + } else { + *const_cast<_Vbase*>(_Getptr()) &= ~_Mask(); + } + + return *this; + } +#endif // _HAS_CXX23 + + _CONSTEXPR20 void flip() noexcept { + *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); + } + + _CONSTEXPR20 operator bool() const noexcept { + return (*_Getptr() & _Mask()) != 0; + } + + _CONSTEXPR20 const _Vbase* _Getptr() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return this->_Myptr; + } + + friend _CONSTEXPR20 void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { + bool _Val = _Left; // NOT _STD swap + _Left = _Right; + _Right = _Val; + } + +protected: + _CONSTEXPR20 _Vbase _Mask() const noexcept { + return static_cast<_Vbase>(1) << this->_Myoff; + } +}; + +template +class _Vb_const_iterator : public _Vb_iter_base<_Alvbase_wrapped> { +private: + using _Mybase = _Vb_iter_base<_Alvbase_wrapped>; + +public: + using _Mycont = typename _Mybase::_Mycont; + using _Difference_type = typename _Mybase::_Difference_type; + using _Size_type = typename _Mybase::_Size_type; + using _Reft = _Vb_reference<_Alvbase_wrapped>; + using const_reference = bool; + + using iterator_category = random_access_iterator_tag; + using value_type = bool; + using difference_type = typename _Mybase::_Difference_type; + using pointer = const_reference*; + using reference = const_reference; + + _CONSTEXPR20 _Vb_const_iterator() = default; + + _CONSTEXPR20 _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept + : _Mybase(_Ptr, 0, _Mypvbool) {} + + _NODISCARD _CONSTEXPR20 const_reference operator*() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return _Reft(*this); + } + + _CONSTEXPR20 _Vb_const_iterator& operator++() noexcept { + _Inc(); + return *this; + } + + _CONSTEXPR20 _Vb_const_iterator operator++(int) noexcept { + _Vb_const_iterator _Tmp = *this; + _Inc(); + return _Tmp; + } + + _CONSTEXPR20 _Vb_const_iterator& operator--() noexcept { + _Dec(); + return *this; + } + + _CONSTEXPR20 _Vb_const_iterator operator--(int) noexcept { + _Vb_const_iterator _Tmp = *this; + _Dec(); + return _Tmp; + } + + _CONSTEXPR20 _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + if (_Off != 0) { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); + const auto _Start_offset = this->_Total_off(_Cont); + if (_Off < 0) { + _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); + } else if (0 < _Off) { + _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), + "cannot seek vector iterator after end"); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + if (_Off < 0 && this->_Myoff < 0 - static_cast<_Size_type>(_Off)) { // add negative increment + this->_Myoff += static_cast<_Size_type>(_Off); + this->_Myptr -= 1 + (static_cast<_Size_type>(-1) - this->_Myoff) / _VBITS; + this->_Myoff %= _VBITS; + } else { // add non-negative increment + this->_Myoff += static_cast<_Size_type>(_Off); + this->_Myptr += this->_Myoff / _VBITS; + this->_Myoff %= _VBITS; + } + return *this; + } + + _NODISCARD _CONSTEXPR20 _Vb_const_iterator operator+(const difference_type _Off) const noexcept { + _Vb_const_iterator _Tmp = *this; + _Tmp += _Off; + return _Tmp; + } + + _NODISCARD_FRIEND _CONSTEXPR20 _Vb_const_iterator operator+( + const difference_type _Off, _Vb_const_iterator _Right) noexcept { + _Right += _Off; + return _Right; + } + + _CONSTEXPR20 _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { + return *this += -_Off; + } + + _NODISCARD _CONSTEXPR20 _Vb_const_iterator operator-(const difference_type _Off) const noexcept { + _Vb_const_iterator _Tmp = *this; + _Tmp -= _Off; + return _Tmp; + } + + _NODISCARD _CONSTEXPR20 difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { + _Compat(_Right); + return static_cast(_Mybase::_VBITS_DIFF * (this->_Myptr - _Right._Myptr)) + + static_cast(this->_Myoff) - static_cast(_Right._Myoff); + } + + _NODISCARD _CONSTEXPR20 const_reference operator[](const difference_type _Off) const noexcept { + return *(*this + _Off); + } + + _NODISCARD _CONSTEXPR20 bool operator==(const _Vb_const_iterator& _Right) const noexcept { + _Compat(_Right); + return this->_Myptr == _Right._Myptr && this->_Myoff == _Right._Myoff; + } + +#if _HAS_CXX20 + _NODISCARD constexpr strong_ordering operator<=>(const _Vb_const_iterator& _Right) const noexcept { + _Compat(_Right); + if (const auto _CmpResult = this->_Myptr <=> _Right._Myptr; _CmpResult != 0) { + return _CmpResult; + } + return this->_Myoff <=> _Right._Myoff; + } +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv + _NODISCARD bool operator!=(const _Vb_const_iterator& _Right) const noexcept { + return !(*this == _Right); + } + + _NODISCARD bool operator<(const _Vb_const_iterator& _Right) const noexcept { + _Compat(_Right); + return this->_Myptr < _Right._Myptr || (this->_Myptr == _Right._Myptr && this->_Myoff < _Right._Myoff); + } + + _NODISCARD bool operator>(const _Vb_const_iterator& _Right) const noexcept { + return _Right < *this; + } + + _NODISCARD bool operator<=(const _Vb_const_iterator& _Right) const noexcept { + return !(_Right < *this); + } + + _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { + return !(*this < _Right); + } +#endif // !_HAS_CXX20 + + _CONSTEXPR20 void _Compat(const _Vb_const_iterator& _Right) const noexcept { + // test for compatible iterator pair +#if _ITERATOR_DEBUG_LEVEL == 0 + (void) _Right; +#else + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#endif + } + +#if _ITERATOR_DEBUG_LEVEL != 0 + using _Prevent_inheriting_unwrap = _Vb_const_iterator; + + friend _CONSTEXPR20 void _Verify_range(const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { + // note _Compat check inside <= + _STL_VERIFY(_First <= _Last, "vector iterator range transposed"); + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + _CONSTEXPR20 void _Dec() noexcept { // decrement bit position +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + if (this->_Myoff != 0) { + --this->_Myoff; + } else { // move to previous word + this->_Myoff = _VBITS - 1; + --this->_Myptr; + } + } + + _CONSTEXPR20 void _Inc() noexcept { // increment bit position +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "cannot increment vector end iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + if (this->_Myoff < _VBITS - 1) { + ++this->_Myoff; + } else { // move to next word + this->_Myoff = 0; + ++this->_Myptr; + } + } +}; + +template +class _Vb_iterator : public _Vb_const_iterator<_Alvbase_wrapped> { +public: + using _Mybase = _Vb_const_iterator<_Alvbase_wrapped>; + using _Mycont = typename _Mybase::_Mycont; + using _Difference_type = typename _Mybase::_Difference_type; + + using _Reft = _Vb_reference<_Alvbase_wrapped>; + using const_reference = bool; + + using iterator_category = random_access_iterator_tag; + using value_type = bool; + using difference_type = typename _Mybase::difference_type; + using pointer = _Reft*; + using reference = _Reft; + + using _Mybase::_Mybase; + + _NODISCARD _CONSTEXPR20 reference operator*() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return _Reft(*this); + } + + _CONSTEXPR20 _Vb_iterator& operator++() noexcept { + _Mybase::operator++(); + return *this; + } + + _CONSTEXPR20 _Vb_iterator operator++(int) noexcept { + _Vb_iterator _Tmp = *this; + _Mybase::operator++(); + return _Tmp; + } + + _CONSTEXPR20 _Vb_iterator& operator--() noexcept { + _Mybase::operator--(); + return *this; + } + + _CONSTEXPR20 _Vb_iterator operator--(int) noexcept { + _Vb_iterator _Tmp = *this; + _Mybase::operator--(); + return _Tmp; + } + + _CONSTEXPR20 _Vb_iterator& operator+=(const difference_type _Off) noexcept { + _Mybase::operator+=(_Off); + return *this; + } + + _NODISCARD _CONSTEXPR20 _Vb_iterator operator+(const difference_type _Off) const noexcept { + _Vb_iterator _Tmp = *this; + _Tmp += _Off; + return _Tmp; + } + + _NODISCARD_FRIEND _CONSTEXPR20 _Vb_iterator operator+(const difference_type _Off, _Vb_iterator _Right) noexcept { + _Right += _Off; + return _Right; + } + + _CONSTEXPR20 _Vb_iterator& operator-=(const difference_type _Off) noexcept { + _Mybase::operator-=(_Off); + return *this; + } + + using _Mybase::operator-; + + _NODISCARD _CONSTEXPR20 _Vb_iterator operator-(const difference_type _Off) const noexcept { + _Vb_iterator _Tmp = *this; + _Tmp -= _Off; + return _Tmp; + } + + _NODISCARD _CONSTEXPR20 reference operator[](const difference_type _Off) const noexcept { + return *(*this + _Off); + } + + using _Prevent_inheriting_unwrap = _Vb_iterator; +}; + +template +class _Vb_val : public _Container_base { +public: + using _Alvbase = _Rebind_alloc_t<_Alloc, _Vbase>; + using _Alvbase_traits = allocator_traits<_Alvbase>; + using _Vectype = vector<_Vbase, _Alvbase>; + using _Alvbase_wrapped = _Wrap_alloc<_Alvbase>; + using size_type = typename _Alvbase_traits::size_type; + + _CONSTEXPR20 _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(const _Alloc& _Al) noexcept : _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(size_type _Count, const bool& _Val) + : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) + : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0), static_cast<_Alvbase>(_Al)), _Mysize(0) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) + : _Myvec(_Right._Myvec, static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) + : _Myvec(_STD move(_Right._Myvec)), _Mysize(_STD exchange(_Right._Mysize, size_type{0})) { + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) + : _Myvec(_STD move(_Right._Myvec), static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { + if (_Right._Myvec.empty()) { + // we took _Right's buffer, so zero out size + _Right._Mysize = 0; + } + + this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); + } + + _CONSTEXPR20 ~_Vb_val() noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + this->_Orphan_all(); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alvbase, this->_Getal()); + _Delete_plain_internal(_Alproxy, _STD exchange(this->_Myproxy, nullptr)); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + } + + _CONSTEXPR20 _Alvbase& _Getal() noexcept { + return _Myvec._Getal(); + } + + _CONSTEXPR20 const _Alvbase& _Getal() const noexcept { + return _Myvec._Getal(); + } + + static _CONSTEXPR20 size_type _Nw(size_type _Count) noexcept { + return (_Count + _VBITS - 1) / _VBITS; + } + + _CONSTEXPR20 void _Emplace_back_unchecked(const _Vbase _Val) noexcept { + _STL_INTERNAL_CHECK(_Myvec.size() < _Myvec.capacity()); + _Myvec._Emplace_back_with_unused_capacity(_Val); + } + + _Vectype _Myvec; // base vector of words + size_type _Mysize; // current length of sequence +}; + +template +class vector : public _Vb_val<_Alloc> { +public: + static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v, + _MISMATCHED_ALLOCATOR_MESSAGE("vector", "bool")); + + using _Mybase = _Vb_val<_Alloc>; + using _Alvbase_wrapped = typename _Mybase::_Alvbase_wrapped; + using _Alvbase = typename _Mybase::_Alvbase; + using _Alvbase_traits = typename _Mybase::_Alvbase_traits; + + using size_type = typename _Alvbase_traits::size_type; + using difference_type = typename _Alvbase_traits::difference_type; + using allocator_type = _Alloc; + + using reference = _Vb_reference<_Alvbase_wrapped>; + using const_reference = bool; + using value_type = bool; + + using _Reft = reference; + using iterator = _Vb_iterator<_Alvbase_wrapped>; + using const_iterator = _Vb_const_iterator<_Alvbase_wrapped>; + + using pointer = iterator; + using const_pointer = const_iterator; + using reverse_iterator = _STD reverse_iterator; + using const_reverse_iterator = _STD reverse_iterator; + + enum { _EEN_VBITS = _VBITS }; // helper for expression evaluator + + _CONSTEXPR20 vector() noexcept(is_nothrow_default_constructible_v<_Alloc>) : _Mybase(_Alloc()) {} + + _CONSTEXPR20 explicit vector(const _Alloc& _Al) noexcept : _Mybase(_Al) {} + + _CONSTEXPR20 explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) + : _Mybase(_Count, false, _Al) { + _Trim(_Count); + } + + _CONSTEXPR20 vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) + : _Mybase(_Count, _Val, _Al) { + _Trim(_Count); + } + + _CONSTEXPR20 vector(const vector& _Right) : _Mybase(_Right) {} + + _CONSTEXPR20 vector(const vector& _Right, const _Identity_t<_Alloc>& _Al) : _Mybase(_Right, _Al) {} + + template , int> = 0> + _CONSTEXPR20 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { + insert(begin(), _First, _Last); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range _Rng> + constexpr vector(from_range_t, _Rng&& _Range, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { + if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); + } else { + _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 vector(vector&& _Right) noexcept : _Mybase(_STD move(_Right)) { + this->_Swap_proxy_and_iterators(_Right); + } + + _CONSTEXPR20 vector(vector&& _Right, const _Identity_t<_Alloc>& _Al) noexcept( + is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) // strengthened + : _Mybase(_STD move(_Right), _Al) { + if constexpr (!_Alvbase_traits::is_always_equal::value) { + if (this->_Getal() != _Right._Getal()) { + return; + } + } + + this->_Swap_proxy_and_iterators(_Right); + } + + _CONSTEXPR20 vector& operator=(vector&& _Right) noexcept( + _Choose_pocma_v<_Alvbase> != _Pocma_values::_No_propagate_allocators) { + if (this == _STD addressof(_Right)) { + return *this; + } + +#if _ITERATOR_DEBUG_LEVEL == 0 + this->_Myvec = _STD move(_Right._Myvec); + this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv + this->_Orphan_all(); + auto& _Al = this->_Getal(); + auto& _Right_al = _Right._Getal(); + constexpr auto _Pocma_val = _Choose_pocma_v<_Alvbase>; + if constexpr (_Pocma_val == _Pocma_values::_Propagate_allocators) { + using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; + if (_Al != _Right_al) { // reload proxy + // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 + _Alproxy_type _Oldal(_Al); + _Alproxy_type _Right_proxy_al(_Right_al); + _Container_proxy_ptr<_Alvbase> _Proxy(_Right_proxy_al, _Leave_proxy_unbound{}); + this->_Myvec = _STD move(_Right._Myvec); + this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); + _Proxy._Bind(_Oldal, this); + this->_Swap_proxy_and_iterators(_Right); + return *this; + } + } else if constexpr (_Pocma_val == _Pocma_values::_No_propagate_allocators) { + this->_Myvec = _STD move(_Right._Myvec); + this->_Mysize = _Right._Mysize; + if (_Right._Myvec.empty()) { + // we took _Right's buffer, so zero out size + _Right._Mysize = 0; + } + + if (_Al == _Right_al) { + this->_Swap_proxy_and_iterators(_Right); + } + return *this; + } + + this->_Myvec = _STD move(_Right._Myvec); + this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); + this->_Swap_proxy_and_iterators(_Right); + +#endif // _ITERATOR_DEBUG_LEVEL == 0 + return *this; + } + + template + _CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) { + bool _Tmp(_STD forward<_Valty>(_Val)...); + push_back(_Tmp); + +#if _HAS_CXX17 + return back(); +#endif // _HAS_CXX17 + } + + template + _CONSTEXPR20 iterator emplace(const_iterator _Where, _Valty&&... _Val) { + bool _Tmp(_STD forward<_Valty>(_Val)...); + return insert(_Where, _Tmp); + } + + _CONSTEXPR20 vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) : _Mybase(0, false, _Al) { + insert(begin(), _Ilist.begin(), _Ilist.end()); + } + + _CONSTEXPR20 vector& operator=(initializer_list _Ilist) { + assign(_Ilist.begin(), _Ilist.end()); + return *this; + } + + _CONSTEXPR20 void assign(initializer_list _Ilist) { + assign(_Ilist.begin(), _Ilist.end()); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, initializer_list _Ilist) { + return insert(_Where, _Ilist.begin(), _Ilist.end()); + } + + _CONSTEXPR20 ~vector() noexcept {} + + _CONSTEXPR20 vector& operator=(const vector& _Right) { + if (this == _STD addressof(_Right)) { + return *this; + } + +#if _ITERATOR_DEBUG_LEVEL == 0 + this->_Myvec = _Right._Myvec; + this->_Mysize = _Right._Mysize; +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv + this->_Orphan_all(); + auto& _Al = this->_Getal(); + auto& _Right_al = _Right._Getal(); + if constexpr (_Choose_pocca_v<_Alvbase>) { + if (_Al != _Right_al) { + // reload proxy + using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; + _Alproxy_type _Oldal(_Al); + _Alproxy_type _Right_proxy_al(_Right_al); + _Container_proxy_ptr<_Alvbase> _Proxy(_Right_proxy_al, _Leave_proxy_unbound{}); + this->_Myvec = _Right._Myvec; + this->_Mysize = _Right._Mysize; + _Proxy._Bind(_Oldal, this); + return *this; + } + } + + this->_Myvec = _Right._Myvec; + this->_Mysize = _Right._Mysize; +#endif // _ITERATOR_DEBUG_LEVEL == 0 + + return *this; + } + + _CONSTEXPR20 void reserve(_CRT_GUARDOVERFLOW size_type _Count) { + this->_Myvec.reserve(this->_Nw(_Count)); + } + + _NODISCARD _CONSTEXPR20 size_type capacity() const noexcept { + return this->_Myvec.capacity() * _VBITS; + } + + _NODISCARD _CONSTEXPR20 iterator begin() noexcept { + return iterator(this->_Myvec.data(), this); + } + + _NODISCARD _CONSTEXPR20 const_iterator begin() const noexcept { + return const_iterator(this->_Myvec.data(), this); + } + + _NODISCARD _CONSTEXPR20 iterator end() noexcept { + return begin() + static_cast(this->_Mysize); + } + + _NODISCARD _CONSTEXPR20 const_iterator end() const noexcept { + return begin() + static_cast(this->_Mysize); + } + + _NODISCARD _CONSTEXPR20 const_iterator cbegin() const noexcept { + return begin(); + } + + _NODISCARD _CONSTEXPR20 const_iterator cend() const noexcept { + return end(); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { + return rbegin(); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator crend() const noexcept { + return rend(); + } + + _NODISCARD _CONSTEXPR20 iterator _Unchecked_begin() noexcept { + return iterator(this->_Myvec.data(), this); + } + + _NODISCARD _CONSTEXPR20 const_iterator _Unchecked_begin() const noexcept { + return const_iterator(this->_Myvec.data(), this); + } + + _NODISCARD _CONSTEXPR20 iterator _Unchecked_end() noexcept { + return _Unchecked_begin() + static_cast(this->_Mysize); + } + + _NODISCARD _CONSTEXPR20 const_iterator _Unchecked_end() const noexcept { + return _Unchecked_begin() + static_cast(this->_Mysize); + } + + _CONSTEXPR20 void shrink_to_fit() { + if (this->_Myvec.capacity() != this->_Myvec.size()) { + this->_Orphan_all(); + this->_Myvec.shrink_to_fit(); + } + } + + _CONSTEXPR20 iterator _Make_iter(const_iterator _Where) noexcept { + iterator _Tmp = begin(); + if (0 < this->_Mysize) { + _Tmp += _Where - begin(); + } + + return _Tmp; + } + + _NODISCARD _CONSTEXPR20 reverse_iterator rbegin() noexcept { + return reverse_iterator(end()); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator(end()); + } + + _NODISCARD _CONSTEXPR20 reverse_iterator rend() noexcept { + return reverse_iterator(begin()); + } + + _NODISCARD _CONSTEXPR20 const_reverse_iterator rend() const noexcept { + return const_reverse_iterator(begin()); + } + + _CONSTEXPR20 void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { + if (size() < _Newsize) { + _Insert_n(end(), _Newsize - size(), _Val); + } else if (_Newsize < size()) { + erase(begin() + static_cast(_Newsize), end()); + } + } + + _NODISCARD _CONSTEXPR20 size_type size() const noexcept { + return this->_Mysize; + } + + _NODISCARD _CONSTEXPR20 size_type max_size() const noexcept { + constexpr auto _Diff_max = static_cast((numeric_limits::max)()); + const size_type _Ints_max = this->_Myvec.max_size(); + if (_Ints_max > _Diff_max / _VBITS) { // max_size bound by difference_type limits + return _Diff_max; + } + + // max_size bound by underlying storage limits + return _Ints_max * _VBITS; + } + + _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { + return this->_Mysize == 0; + } + + _NODISCARD _CONSTEXPR20 allocator_type get_allocator() const noexcept { + return static_cast(this->_Myvec.get_allocator()); + } + + _NODISCARD _CONSTEXPR20 const_reference at(size_type _Off) const { + if (size() <= _Off) { + _Xran(); + } + + return (*this)[_Off]; + } + + _NODISCARD _CONSTEXPR20 reference at(size_type _Off) { + if (size() <= _Off) { + _Xran(); + } + + return (*this)[_Off]; + } + + _NODISCARD _CONSTEXPR20 const_reference operator[](size_type _Off) const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + const_iterator _It = begin(); + _It._Advance(_Off); + return *_It; + } + + _NODISCARD _CONSTEXPR20 reference operator[](size_type _Off) noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + iterator _It = begin(); + _It._Advance(_Off); + return *_It; + } + + _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *begin(); + } + + _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *begin(); + } + + _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *(end() - 1); + } + + _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 + + return *(end() - 1); + } + + _CONSTEXPR20 void push_back(const bool& _Val) { + insert(end(), _Val); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range _Rng> + constexpr void append_range(_Rng&& _Range) { + insert_range(end(), _STD forward<_Rng>(_Range)); + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { + erase(end() - 1); + } + + template , int> = 0> + _CONSTEXPR20 void assign(_Iter _First, _Iter _Last) { + clear(); + insert(begin(), _First, _Last); + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template + constexpr void _Assign_counted_range(_Iter _First, const size_type _Count) { + _STL_INTERNAL_CHECK(this->_Myvec.empty()); + this->_Myvec.reserve(this->_Nw(_Count)); + _Vbase _Accum = 0; + _Vbase _Mask = 1; + for (size_type _Idx = 0; _Idx < _Count; ++_Idx) { + const bool _Tmp = *_First; + ++_First; + _Accum |= _Tmp ? _Mask : _Vbase{0}; + if ((_Mask <<= 1) == 0) { + this->_Emplace_back_unchecked(_Accum); + _Accum = 0; + _Mask = 1; + } + } + + if (_Count % _VBITS != 0) { + this->_Emplace_back_unchecked(_Accum); + } + this->_Mysize = _Count; + } + + template + constexpr void _Assign_uncounted_range(_Iter _First, const _Sent _Last) { + _STL_INTERNAL_CHECK(this->_Myvec.empty()); + size_type _Count = 0; + _Vbase _Accum = 0; + _Vbase _Mask = 1; + for (; _First != _Last; ++_Count) { + const bool _Tmp = *_First; + ++_First; + _Accum |= _Tmp ? _Mask : _Vbase{0}; + if ((_Mask <<= 1) == 0) { + this->_Myvec.push_back(_Accum); + _Accum = 0; + _Mask = 1; + } + } + + if (_Count % _VBITS != 0) { + this->_Myvec.push_back(_Accum); + } + this->_Mysize = _Count; + } + + template <_Container_compatible_range _Rng> + constexpr void assign_range(_Rng&& _Range) { + clear(); + if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + _Assign_counted_range(_RANGES _Ubegin(_Range), _Count); + } else { + _Assign_uncounted_range(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range)); + } + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + clear(); + _Insert_n(begin(), _Count, _Val); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, const bool& _Val) { + return _Insert_n(_Where, size_type{1}, _Val); + } + + _CONSTEXPR20 iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + return _Insert_n(_Where, _Count, _Val); + } + + template , int> = 0> + _CONSTEXPR20 iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + const difference_type _Saved_offset = _Where - begin(); + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_First); + const auto _ULast = _Get_unwrapped(_Last); + + if constexpr (_Is_cpp17_fwd_iter_v<_Iter>) { + const auto _Length = static_cast(_STD distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + const auto _Off = static_cast(_Insert_x(_Where, _Count)); + _STD _Copy_unchecked(_UFirst, _ULast, begin() + _Off); +#ifdef __cpp_lib_concepts + } else if constexpr (forward_iterator<_Iter>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_UFirst, _ULast)); + const auto _Count = _Convert_size(_Length); + const auto _Off = static_cast(_Insert_x(_Where, _Count)); + _STD _Copy_unchecked(_UFirst, _ULast, begin() + _Off); +#endif // defined(__cpp_lib_concepts) + } else { + const auto _Old_size = this->_Mysize; + for (; _UFirst != _ULast; ++_UFirst) { + emplace_back(*_UFirst); + } +#if _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(static_cast(_Saved_offset), _Old_size); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + _STD rotate(begin() + _Saved_offset, begin() + static_cast(_Old_size), end()); + } + + return begin() + _Saved_offset; + } + +#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 + template <_Container_compatible_range _Rng> + constexpr iterator insert_range(const_iterator _Where, _Rng&& _Range) { + const difference_type _Old_off = _Where - begin(); + + if constexpr (_RANGES forward_range<_Rng> || _RANGES sized_range<_Rng>) { + const auto _Length = _To_unsigned_like(_RANGES distance(_Range)); + const auto _Count = _Convert_size(_Length); + const auto _Off = static_cast(_Insert_x(_Where, _Count)); + _Copy_n_unchecked4(_RANGES _Ubegin(_Range), _Count, begin() + _Off); + } else { + auto _UFirst = _RANGES _Ubegin(_Range); + const auto _ULast = _RANGES _Uend(_Range); + const auto _Old_size = this->_Mysize; + for (; _UFirst != _ULast; ++_UFirst) { + emplace_back(*_UFirst); + } +#if _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(static_cast(_Old_off), _Old_size); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + _STD rotate(begin() + _Old_off, begin() + static_cast(_Old_size), end()); + } + + return begin() + _Old_off; + } +#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) + + _CONSTEXPR20 iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { + iterator _Where = _Make_iter(_Where_arg); + difference_type _Off = _Where - begin(); + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(end() > _Where, "vector erase iterator outside range"); + _STD copy(_Next_iter(_Where), end(), _Where); + _Orphan_range(static_cast(_Off), this->_Mysize); + +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv + _STD copy(_Next_iter(_Where), end(), _Where); +#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ + + _Trim(this->_Mysize - 1); + return begin() + _Off; + } + + _CONSTEXPR20 iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept + /* strengthened */ { + iterator _First = _Make_iter(_First_arg); + iterator _Last = _Make_iter(_Last_arg); + difference_type _Off = _First - begin(); + + if (_First != _Last) { // worth doing, copy down over hole +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(_Last >= _First && end() >= _Last, "vector erase iterator outside range"); + iterator _Next = _STD copy(_Last, end(), _First); + const auto _Newsize = static_cast(_Next - begin()); + _Orphan_range(_Newsize, this->_Mysize); + _Trim(_Newsize); + +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv + iterator _Next = _STD copy(_Last, end(), _First); + _Trim(static_cast(_Next - begin())); +#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ + } + return begin() + _Off; + } + + _CONSTEXPR20 void clear() noexcept { + this->_Orphan_all(); + this->_Myvec.clear(); + this->_Mysize = 0; + } + + _CONSTEXPR20 void flip() noexcept { // toggle all elements + for (auto& _Elem : this->_Myvec) { + _Elem = ~_Elem; + } + + _Trim(this->_Mysize); + } + + _CONSTEXPR20 void swap(vector& _Right) noexcept /* strengthened */ { + if (this != _STD addressof(_Right)) { + this->_Swap_proxy_and_iterators(_Right); + this->_Myvec.swap(_Right._Myvec); + _STD swap(this->_Mysize, _Right._Mysize); + } + } + + static _CONSTEXPR20 void swap(reference _Left, reference _Right) noexcept { + bool _Val = _Left; // NOT _STD swap + _Left = _Right; + _Right = _Val; + } + + friend hash>; + + _CONSTEXPR20 iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { + size_type _Off = _Insert_x(_Where, _Count); + const auto _Result = begin() + static_cast(_Off); + _STD fill_n(_Result, _Count, _Val); + return _Result; + } + + _CONSTEXPR20 size_type _Insert_x(const_iterator _Where, size_type _Count) { + const difference_type _Off = _Where - begin(); + +#if _ITERATOR_DEBUG_LEVEL == 2 + _STL_VERIFY(end() >= _Where, "vector insert iterator outside range"); + const bool _Realloc = capacity() - size() < _Count; +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + if (_Count != 0) { + if (max_size() - size() < _Count) { + _Xlen(); // result too long + } + +#if _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(static_cast(_Realloc ? 0 : _Off), this->_Mysize); +#endif // _ITERATOR_DEBUG_LEVEL == 2 + this->_Myvec.resize(this->_Nw(size() + _Count), 0); + if (empty()) { + this->_Mysize += _Count; + } else { // make room and copy down suffix + iterator _Oldend = end(); + this->_Mysize += _Count; + _STD copy_backward(begin() + _Off, _Oldend, end()); + } + } + + return static_cast(_Off); + } + +#if _ITERATOR_DEBUG_LEVEL == 2 + _CONSTEXPR20 void _Orphan_range_unlocked(size_type _Offlo, size_type _Offhi) const { + const auto _Base = this->_Myvec.data(); + + _Iterator_base12** _Pnext = &this->_Myproxy->_Myfirstiter; + while (*_Pnext) { // test offset from beginning of vector + const auto& _Pnextiter = static_cast(**_Pnext); + const auto _Temp = *_Pnext; + if (!_Pnextiter._Myptr) { // orphan the iterator + _Temp->_Myproxy = nullptr; + *_Pnext = _Temp->_Mynextiter; + continue; + } + const auto _Off = + static_cast(const_iterator::_VBITS_DIFF * (_Pnextiter._Myptr - _Base)) + _Pnextiter._Myoff; + if (_Off < _Offlo || _Offhi < _Off) { + _Pnext = &_Temp->_Mynextiter; + } else { // orphan the iterator + _Temp->_Myproxy = nullptr; + *_Pnext = _Temp->_Mynextiter; + } + } + } + + void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_Offlo, _Offhi); + } + + _CONSTEXPR20 void _Orphan_range(size_type _Offlo, size_type _Offhi) const { +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_Offlo, _Offhi); + } else +#endif // _HAS_CXX20 + { + _Orphan_range_locked(_Offlo, _Offhi); + } + } +#endif // _ITERATOR_DEBUG_LEVEL == 2 + + _CONSTEXPR20 void _Trim(size_type _Size) { + if (max_size() < _Size) { + _Xlen(); // result too long + } + + const size_type _Words = this->_Nw(_Size); + if (_Words < this->_Myvec.size()) { + this->_Myvec.erase(this->_Myvec.begin() + static_cast(_Words), this->_Myvec.end()); + } + + this->_Mysize = _Size; + _Size %= _VBITS; + if (0 < _Size) { + this->_Myvec[_Words - 1] &= (static_cast<_Vbase>(1) << _Size) - 1; + } + } + + [[noreturn]] static void _Xlen() { + _Xlength_error("vector too long"); + } + + [[noreturn]] static void _Xran() { + _Xout_of_range("invalid vector subscript"); + } +}; + +template +struct hash> { + using _ARGUMENT_TYPE_NAME _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS = vector; + using _RESULT_TYPE_NAME _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS = size_t; + + _NODISCARD size_t operator()(const vector& _Keyval) const noexcept { + return _Hash_array_representation(_Keyval._Myvec.data(), _Keyval._Myvec.size()); + } +}; + +#if _HAS_CXX17 +namespace pmr { + _EXPORT_STD template + using vector = _STD vector<_Ty, polymorphic_allocator<_Ty>>; +} // namespace pmr +#endif // _HAS_CXX17 + +template +_INLINE_VAR constexpr bool _Is_vb_iterator<_Vb_iterator<_Alloc>, _RequiresMutable> = true; + +template +_INLINE_VAR constexpr bool _Is_vb_iterator<_Vb_const_iterator<_Alloc>, false> = true; + +template +_CONSTEXPR20 void _Fill_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { + // Set [_First, _Last) to _Val + if (_First == _Last) { + return; + } + + _Vbase* _VbFirst = const_cast<_Vbase*>(_First._Myptr); + _Vbase* const _VbLast = const_cast<_Vbase*>(_Last._Myptr); + + const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; + const auto _FirstDestMask = ~_FirstSourceMask; + const auto _FillVal = static_cast<_Vbase>(_Val ? -1 : 0); + + if (_VbFirst == _VbLast) { + // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastDestMask = ~_LastSourceMask; + const auto _SourceMask = _FirstSourceMask & _LastSourceMask; + const auto _DestMask = _FirstDestMask | _LastDestMask; + *_VbFirst = (*_VbFirst & _DestMask) | (_FillVal & _SourceMask); + return; + } + + *_VbFirst = (*_VbFirst & _FirstDestMask) | (_FillVal & _FirstSourceMask); + ++_VbFirst; + +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + for (; _VbFirst != _VbLast; ++_VbFirst) { + *_VbFirst = _FillVal; + } + } else +#endif // _HAS_CXX20 + { + const auto _VbFirst_ch = reinterpret_cast(_VbFirst); + const auto _VbLast_ch = reinterpret_cast(_VbLast); + const auto _Count_ch = static_cast(_VbLast_ch - _VbFirst_ch); + const auto _ValChar = static_cast(_Val ? -1 : 0); + _CSTD memset(_VbFirst, _ValChar, _Count_ch); + _VbFirst = _VbLast; + } + + if (_Last._Myoff != 0) { + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastDestMask = ~_LastSourceMask; + *_VbFirst = (*_VbFirst & _LastDestMask) | (_FillVal & _LastSourceMask); + } +} + +template +_NODISCARD _CONSTEXPR20 _VbIt _Find_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { + // Find _Val in [_First, _Last) + if (_First == _Last) { + return _First; + } + + const _Vbase* _VbFirst = _First._Myptr; + const _Vbase* const _VbLast = _Last._Myptr; + + const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; + + if (_VbFirst == _VbLast) { + // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _SourceMask = _FirstSourceMask & _LastSourceMask; + const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask; + const auto _Count = _Countr_zero(_SelectVal); + return _Count == _VBITS ? _Last : _First + static_cast(_Count - _First._Myoff); + } + + const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask; + const auto _FirstCount = _Countr_zero(_FirstVal); + if (_FirstCount != _VBITS) { + return _First + static_cast(_FirstCount - _First._Myoff); + } + ++_VbFirst; + + _Iter_diff_t<_VbIt> _TotalCount = static_cast(_VBITS - _First._Myoff); + for (; _VbFirst != _VbLast; ++_VbFirst, _TotalCount += _VBITS) { + const auto _SelectVal = _Val ? *_VbFirst : ~*_VbFirst; + const auto _Count = _Countr_zero(_SelectVal); + if (_Count != _VBITS) { + return _First + (_TotalCount + _Count); + } + } + + if (_Last._Myoff != 0) { + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastVal = (_Val ? *_VbFirst : ~*_VbFirst) & _LastSourceMask; + const auto _Count = _Countr_zero(_LastVal); + if (_Count != _VBITS) { + return _First + (_TotalCount + _Count); + } + } + + return _Last; +} + +template +_NODISCARD _CONSTEXPR20 _Iter_diff_t<_VbIt> _Count_vbool(_VbIt _First, const _VbIt _Last, const bool _Val) noexcept { + if (_First == _Last) { + return 0; + } + + const _Vbase* _VbFirst = _First._Myptr; + const _Vbase* const _VbLast = _Last._Myptr; + + const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; + + if (_VbFirst == _VbLast) { + // We already excluded _First == _Last, so here _Last._Myoff > 0 and the shift is safe + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _SourceMask = _FirstSourceMask & _LastSourceMask; + const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask; + return _Popcount(_SelectVal); + } + + return _Select_popcount_impl<_Vbase>( + [_Last, _Val, _VbFirst, _VbLast, _FirstSourceMask](auto _Popcount_impl) mutable noexcept { + const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask; + _Iter_diff_t<_VbIt> _Count = _Popcount_impl(_FirstVal); + ++_VbFirst; + + for (; _VbFirst != _VbLast; ++_VbFirst) { + const auto _SelectVal = _Val ? *_VbFirst : ~*_VbFirst; + _Count += _Popcount_impl(_SelectVal); + } + + if (_Last._Myoff != 0) { + const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastVal = (_Val ? *_VbFirst : ~*_VbFirst) & _LastSourceMask; + _Count += _Popcount_impl(_LastVal); + } + + return _Count; + }); +} + +#undef _ASAN_VECTOR_MODIFY +#undef _ASAN_VECTOR_REMOVE +#undef _ASAN_VECTOR_CREATE +#undef _ASAN_VECTOR_CREATE_GUARD +#undef _ASAN_VECTOR_EXTEND_GUARD +#undef _ASAN_VECTOR_RELEASE_GUARD +#undef _INSERT_VECTOR_ANNOTATION +_STD_END + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _VECTOR_