// deque standard header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _DEQUE_ #define _DEQUE_ #include #if _STL_COMPILER_PREPROCESSOR #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 // DEQUE PARAMETERS #define _DEQUEMAPSIZ 8 // minimum map size, at least 1 #define _DEQUESIZ \ (sizeof(value_type) <= 1 \ ? 16 \ : sizeof(value_type) <= 2 \ ? 8 \ : sizeof(value_type) <= 4 ? 4 \ : sizeof(value_type) <= 8 ? 2 : 1) // elements per block (a power of 2) // CLASS TEMPLATE _Deque_unchecked_const_iterator template class _Deque_unchecked_const_iterator { private: using _Size_type = typename _Mydeque::size_type; public: using iterator_category = random_access_iterator_tag; using value_type = typename _Mydeque::value_type; using difference_type = typename _Mydeque::difference_type; using pointer = typename _Mydeque::const_pointer; using reference = const value_type&; _Deque_unchecked_const_iterator() noexcept : _Mycont(), _Myoff(0) {} _Deque_unchecked_const_iterator(_Size_type _Off, const _Container_base12* _Pdeque) noexcept : _Mycont(static_cast(_Pdeque)), _Myoff(_Off) {} _NODISCARD reference operator*() const { _Size_type _Block = _Mycont->_Getblock(_Myoff); _Size_type _Off = _Myoff % _DEQUESIZ; return _Mycont->_Map[_Block][_Off]; } _NODISCARD pointer operator->() const { return pointer_traits::pointer_to(**this); } _Deque_unchecked_const_iterator& operator++() { ++_Myoff; return *this; } _Deque_unchecked_const_iterator operator++(int) { _Deque_unchecked_const_iterator _Tmp = *this; ++_Myoff; return _Tmp; } _Deque_unchecked_const_iterator& operator--() { --_Myoff; return *this; } _Deque_unchecked_const_iterator operator--(int) { _Deque_unchecked_const_iterator _Tmp = *this; --_Myoff; return _Tmp; } _Deque_unchecked_const_iterator& operator+=(const difference_type _Off) { _Myoff += _Off; return *this; } _NODISCARD _Deque_unchecked_const_iterator operator+(const difference_type _Off) const { _Deque_unchecked_const_iterator _Tmp = *this; return _Tmp += _Off; } _Deque_unchecked_const_iterator& operator-=(const difference_type _Off) { _Myoff -= _Off; return *this; } _NODISCARD _Deque_unchecked_const_iterator operator-(const difference_type _Off) const { _Deque_unchecked_const_iterator _Tmp = *this; return _Tmp -= _Off; } _NODISCARD difference_type operator-(const _Deque_unchecked_const_iterator& _Right) const { return static_cast(_Myoff - _Right._Myoff); } _NODISCARD reference operator[](const difference_type _Off) const { return *(*this + _Off); } _NODISCARD bool operator==(const _Deque_unchecked_const_iterator& _Right) const { return _Myoff == _Right._Myoff; } _NODISCARD bool operator!=(const _Deque_unchecked_const_iterator& _Right) const { return !(*this == _Right); } _NODISCARD bool operator<(const _Deque_unchecked_const_iterator& _Right) const { return _Myoff < _Right._Myoff; } _NODISCARD bool operator>(const _Deque_unchecked_const_iterator& _Right) const { return _Right < *this; } _NODISCARD bool operator<=(const _Deque_unchecked_const_iterator& _Right) const { return !(_Right < *this); } _NODISCARD bool operator>=(const _Deque_unchecked_const_iterator& _Right) const { return !(*this < _Right); } const _Container_base12* _Getcont() const { // get container pointer return _Mycont; } const _Mydeque* _Mycont; _Size_type _Myoff; // offset of element in deque }; template _NODISCARD _Deque_unchecked_const_iterator<_Mydeque> operator+( typename _Deque_unchecked_const_iterator<_Mydeque>::difference_type _Off, _Deque_unchecked_const_iterator<_Mydeque> _Next) { return _Next += _Off; } // CLASS TEMPLATE _Deque_unchecked_iterator template class _Deque_unchecked_iterator : public _Deque_unchecked_const_iterator<_Mydeque> { private: using _Size_type = typename _Mydeque::size_type; using _Mybase = _Deque_unchecked_const_iterator<_Mydeque>; public: using iterator_category = random_access_iterator_tag; using value_type = typename _Mydeque::value_type; using difference_type = typename _Mydeque::difference_type; using pointer = typename _Mydeque::pointer; using reference = value_type&; using _Mybase::_Mybase; _NODISCARD reference operator*() const { return const_cast(_Mybase::operator*()); } _NODISCARD pointer operator->() const { return pointer_traits::pointer_to(**this); } _Deque_unchecked_iterator& operator++() { _Mybase::operator++(); return *this; } _Deque_unchecked_iterator operator++(int) { _Deque_unchecked_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } _Deque_unchecked_iterator& operator--() { _Mybase::operator--(); return *this; } _Deque_unchecked_iterator operator--(int) { _Deque_unchecked_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } _Deque_unchecked_iterator& operator+=(const difference_type _Off) { _Mybase::operator+=(_Off); return *this; } _NODISCARD _Deque_unchecked_iterator operator+(const difference_type _Off) const { _Deque_unchecked_iterator _Tmp = *this; return _Tmp += _Off; } _Deque_unchecked_iterator& operator-=(const difference_type _Off) { _Mybase::operator-=(_Off); return *this; } _NODISCARD _Deque_unchecked_iterator operator-(const difference_type _Off) const { _Deque_unchecked_iterator _Tmp = *this; return _Tmp -= _Off; } _NODISCARD difference_type operator-(const _Mybase& _Right) const { return _Mybase::operator-(_Right); } _NODISCARD reference operator[](const difference_type _Off) const { return const_cast(_Mybase::operator[](_Off)); } }; template _NODISCARD _Deque_unchecked_iterator<_Mydeque> operator+( typename _Deque_unchecked_iterator<_Mydeque>::difference_type _Off, _Deque_unchecked_iterator<_Mydeque> _Next) { return _Next += _Off; } // CLASS TEMPLATE _Deque_const_iterator template class _Deque_const_iterator : public _Iterator_base12 { private: using _Size_type = typename _Mydeque::size_type; public: using iterator_category = random_access_iterator_tag; using value_type = typename _Mydeque::value_type; using difference_type = typename _Mydeque::difference_type; using pointer = typename _Mydeque::const_pointer; using reference = const value_type&; using _Mydeque_t = _Mydeque; // helper for expression evaluator enum { _EEN_DS = _DEQUESIZ }; // helper for expression evaluator _Deque_const_iterator() noexcept : _Myoff(0) { _Setcont(nullptr); } _Deque_const_iterator(_Size_type _Off, const _Container_base12* _Pdeque) noexcept : _Myoff(_Off) { _Setcont(static_cast(_Pdeque)); } _NODISCARD reference operator*() const { const auto _Mycont = static_cast(this->_Getcont()); #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mycont, "cannot dereference value-initialized deque iterator"); _STL_VERIFY(_Mycont->_Myoff <= this->_Myoff && this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize, "cannot deference out of range deque iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Size_type _Block = _Mycont->_Getblock(_Myoff); _Size_type _Off = _Myoff % _DEQUESIZ; return _Mycont->_Map[_Block][_Off]; } _NODISCARD pointer operator->() const { return pointer_traits::pointer_to(**this); } _Deque_const_iterator& operator++() { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Mycont, "cannot increment value-initialized deque iterator"); _STL_VERIFY(this->_Myoff < _Mycont->_Myoff + _Mycont->_Mysize, "cannot increment deque iterator past end"); #endif // _ITERATOR_DEBUG_LEVEL != 0 ++_Myoff; return *this; } _Deque_const_iterator operator++(int) { _Deque_const_iterator _Tmp = *this; ++*this; return _Tmp; } _Deque_const_iterator& operator--() { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Mycont, "cannot decrement value-initialized deque iterator"); _STL_VERIFY(_Mycont->_Myoff < this->_Myoff, "cannot decrement deque iterator before begin"); #endif // _ITERATOR_DEBUG_LEVEL != 0 --_Myoff; return *this; } _Deque_const_iterator operator--(int) { _Deque_const_iterator _Tmp = *this; --*this; return _Tmp; } _Deque_const_iterator& operator+=(const difference_type _Off) { #if _ITERATOR_DEBUG_LEVEL != 0 if (_Off != 0) { const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Mycont, "cannot seek value-initialized deque iterator"); _STL_VERIFY( _Mycont->_Myoff <= this->_Myoff + _Off && this->_Myoff + _Off <= _Mycont->_Myoff + _Mycont->_Mysize, "cannot seek deque iterator out of range"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 _Myoff += _Off; return *this; } _NODISCARD _Deque_const_iterator operator+(const difference_type _Off) const { _Deque_const_iterator _Tmp = *this; return _Tmp += _Off; } _Deque_const_iterator& operator-=(const difference_type _Off) { return *this += -_Off; } _NODISCARD _Deque_const_iterator operator-(const difference_type _Off) const { _Deque_const_iterator _Tmp = *this; return _Tmp -= _Off; } _NODISCARD difference_type operator-(const _Deque_const_iterator& _Right) const { _Compat(_Right); return static_cast(this->_Myoff - _Right._Myoff); } _NODISCARD reference operator[](const difference_type _Off) const { return *(*this + _Off); } _NODISCARD bool operator==(const _Deque_const_iterator& _Right) const { _Compat(_Right); return this->_Myoff == _Right._Myoff; } _NODISCARD bool operator!=(const _Deque_const_iterator& _Right) const { return !(*this == _Right); } _NODISCARD bool operator<(const _Deque_const_iterator& _Right) const { _Compat(_Right); return this->_Myoff < _Right._Myoff; } _NODISCARD bool operator>(const _Deque_const_iterator& _Right) const { return _Right < *this; } _NODISCARD bool operator<=(const _Deque_const_iterator& _Right) const { return !(_Right < *this); } _NODISCARD bool operator>=(const _Deque_const_iterator& _Right) const { return !(*this < _Right); } void _Compat(const _Deque_const_iterator& _Right) const { // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // _ITERATOR_DEBUG_LEVEL == 0 _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "deque iterators incompatible"); #endif // _ITERATOR_DEBUG_LEVEL == 0 } void _Setcont(const _Mydeque* _Pdeque) { // set container pointer this->_Adopt(_Pdeque); } using _Prevent_inheriting_unwrap = _Deque_const_iterator; _NODISCARD _Deque_unchecked_const_iterator<_Mydeque> _Unwrapped() const { return {this->_Myoff, this->_Getcont()}; } void _Verify_offset(const difference_type _Off) const noexcept { #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Off; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv if (_Off != 0) { const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Mycont, "cannot use value-initialized deque iterator"); _STL_VERIFY( _Mycont->_Myoff <= this->_Myoff + _Off && this->_Myoff + _Off <= _Mycont->_Myoff + _Mycont->_Mysize, "cannot seek deque iterator out of range"); } #endif // _ITERATOR_DEBUG_LEVEL == 0 } #if _ITERATOR_DEBUG_LEVEL != 0 friend void _Verify_range(const _Deque_const_iterator& _First, const _Deque_const_iterator& _Last) { // note _Compat check inside operator<= _STL_VERIFY(_First <= _Last, "deque iterators transposed"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 void _Seek_to(const _Deque_unchecked_const_iterator<_Mydeque>& _UIt) { _Myoff = _UIt._Myoff; } _Size_type _Myoff; // offset of element in deque }; template _NODISCARD _Deque_const_iterator<_Mydeque> operator+( typename _Deque_const_iterator<_Mydeque>::difference_type _Off, _Deque_const_iterator<_Mydeque> _Next) { return _Next += _Off; } // CLASS TEMPLATE _Deque_iterator template class _Deque_iterator : public _Deque_const_iterator<_Mydeque> { private: using _Size_type = typename _Mydeque::size_type; using _Mybase = _Deque_const_iterator<_Mydeque>; public: using _Deque_unchecked_type = _Deque_unchecked_iterator<_Mydeque>; using iterator_category = random_access_iterator_tag; using value_type = typename _Mydeque::value_type; using difference_type = typename _Mydeque::difference_type; using pointer = typename _Mydeque::pointer; using reference = value_type&; using _Mybase::_Mybase; _NODISCARD reference operator*() const { return const_cast(_Mybase::operator*()); } _NODISCARD pointer operator->() const { return pointer_traits::pointer_to(**this); } _Deque_iterator& operator++() { _Mybase::operator++(); return *this; } _Deque_iterator operator++(int) { _Deque_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } _Deque_iterator& operator--() { _Mybase::operator--(); return *this; } _Deque_iterator operator--(int) { _Deque_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } _Deque_iterator& operator+=(const difference_type _Off) { _Mybase::operator+=(_Off); return *this; } _NODISCARD _Deque_iterator operator+(const difference_type _Off) const { _Deque_iterator _Tmp = *this; return _Tmp += _Off; } _Deque_iterator& operator-=(const difference_type _Off) { _Mybase::operator-=(_Off); return *this; } using _Mybase::operator-; _NODISCARD _Deque_iterator operator-(const difference_type _Off) const { _Deque_iterator _Tmp = *this; return _Tmp -= _Off; } _NODISCARD reference operator[](const difference_type _Off) const { return const_cast(_Mybase::operator[](_Off)); } using _Prevent_inheriting_unwrap = _Deque_iterator; _NODISCARD _Deque_unchecked_iterator<_Mydeque> _Unwrapped() const { return {this->_Myoff, this->_Getcont()}; } }; template _NODISCARD _Deque_iterator<_Mydeque> operator+( typename _Deque_iterator<_Mydeque>::difference_type _Off, _Deque_iterator<_Mydeque> _Next) { return _Next += _Off; } // deque TYPE WRAPPERS template struct _Deque_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; using _Mapptr = _Mapptr_type; }; template struct _Deque_simple_types : _Simple_types<_Ty> { using _Mapptr = _Ty**; }; // CLASS TEMPLATE _Deque_val template class _Deque_val : public _Container_base12 { 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&; using _Mapptr = typename _Val_types::_Mapptr; _Deque_val() noexcept : _Map(), _Mapsize(0), _Myoff(0), _Mysize(0) {} size_type _Getblock(size_type _Off) const noexcept { // NB: _Mapsize and _DEQUESIZ are guaranteed to be powers of 2 return (_Off / _DEQUESIZ) & (_Mapsize - 1); } _Mapptr _Map; // pointer to array of pointers to blocks size_type _Mapsize; // size of map array, zero or 2^N size_type _Myoff; // offset of initial element size_type _Mysize; // current length of sequence }; // CLASS TEMPLATE deque template > class deque { private: friend _Tidy_guard; static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Ty, typename _Alloc::value_type>, _MISMATCHED_ALLOCATOR_MESSAGE("deque", "T")); using _Alty = _Rebind_alloc_t<_Alloc, _Ty>; using _Alty_traits = allocator_traits<_Alty>; using _Alpty = _Rebind_alloc_t<_Alloc, typename _Alty_traits::pointer>; using _Alpty_traits = allocator_traits<_Alpty>; using _Mapptr = typename _Alpty_traits::pointer; using _Alproxy_ty = _Rebind_alloc_t<_Alty, _Container_proxy>; using _Alproxy_traits = allocator_traits<_Alproxy_ty>; using _Scary_val = _Deque_val, _Deque_simple_types<_Ty>, _Deque_iter_types<_Ty, typename _Alty_traits::size_type, typename _Alty_traits::difference_type, typename _Alty_traits::pointer, typename _Alty_traits::const_pointer, _Ty&, const _Ty&, _Mapptr>>>; public: using allocator_type = _Alloc; using value_type = _Ty; using size_type = typename _Alty_traits::size_type; using difference_type = typename _Alty_traits::difference_type; using pointer = typename _Alty_traits::pointer; using const_pointer = typename _Alty_traits::const_pointer; using reference = _Ty&; using const_reference = const _Ty&; using iterator = _Deque_iterator<_Scary_val>; using const_iterator = _Deque_const_iterator<_Scary_val>; using _Unchecked_iterator = _Deque_unchecked_iterator<_Scary_val>; using _Unchecked_const_iterator = _Deque_unchecked_const_iterator<_Scary_val>; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; enum { _EEN_DS = _DEQUESIZ }; // helper for expression evaluator deque() : _Mypair(_Zero_then_variadic_args_t{}) { _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); } explicit deque(const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); } explicit deque(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); resize(_Count); _Proxy._Release(); } deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) : _Mypair(_Zero_then_variadic_args_t{}) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct_n(_Count, _Val); _Proxy._Release(); } deque(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct_n(_Count, _Val); _Proxy._Release(); } deque(const deque& _Right) : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); _Proxy._Release(); } deque(const deque& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_Right._Unchecked_begin(), _Right._Unchecked_end()); _Proxy._Release(); } template , int> = 0> deque(_Iter _First, _Iter _Last) : _Mypair(_Zero_then_variadic_args_t{}) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_First, _Last); _Proxy._Release(); } template , int> = 0> deque(_Iter _First, _Iter _Last, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_First, _Last); _Proxy._Release(); } private: template void _Construct(_Iter _First, _Iter _Last) { // initialize from [_First, _Last), input iterators _Tidy_guard _Guard{this}; for (; _First != _Last; ++_First) { emplace_back(*_First); } _Guard._Target = nullptr; } void _Construct_n(size_type _Count, const _Ty& _Val) { // construct from _Count * _Val _Tidy_guard _Guard{this}; for (; 0 < _Count; --_Count) { _Emplace_back_internal(_Val); } _Guard._Target = nullptr; } #define _PUSH_FRONT_BEGIN \ if (_Myoff() % _DEQUESIZ == 0 && _Mapsize() <= (_Mysize() + _DEQUESIZ) / _DEQUESIZ) { \ _Growmap(1); \ } \ _Myoff() &= _Mapsize() * _DEQUESIZ - 1; \ size_type _Newoff = _Myoff() != 0 ? _Myoff() : _Mapsize() * _DEQUESIZ; \ size_type _Block = _Getblock(--_Newoff); \ if (_Map()[_Block] == nullptr) { \ _Map()[_Block] = _Getal().allocate(_DEQUESIZ); \ } #define _PUSH_FRONT_END \ _Myoff() = _Newoff; \ ++_Mysize() #define _PUSH_BACK_BEGIN \ if ((_Myoff() + _Mysize()) % _DEQUESIZ == 0 && _Mapsize() <= (_Mysize() + _DEQUESIZ) / _DEQUESIZ) { \ _Growmap(1); \ } \ _Myoff() &= _Mapsize() * _DEQUESIZ - 1; \ size_type _Newoff = _Myoff() + _Mysize(); \ size_type _Block = _Getblock(_Newoff); \ if (_Map()[_Block] == nullptr) { \ _Map()[_Block] = _Getal().allocate(_DEQUESIZ); \ } #define _PUSH_BACK_END ++_Mysize() public: deque(deque&& _Right) : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal())) { _Get_data()._Alloc_proxy(static_cast<_Alproxy_ty>(_Getal())); _Take_contents(_Right); } deque(deque&& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); if _CONSTEXPR_IF (!_Alty_traits::is_always_equal::value) { if (_Getal() != _Right._Getal()) { _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_STD make_move_iterator(_Right._Unchecked_begin()), _STD make_move_iterator(_Right._Unchecked_end())); _Proxy._Release(); return; } } _Get_data()._Alloc_proxy(_Alproxy); _Take_contents(_Right); } private: void _Move_assign(deque& _Right, _Equal_allocators) noexcept { _Tidy(); _Pocma(_Getal(), _Right._Getal()); _Take_contents(_Right); } void _Move_assign(deque& _Right, _Propagate_allocators) { auto& _Al = _Getal(); auto& _Right_al = _Right._Getal(); if (_Al == _Right_al) { _Move_assign(_Right, _Equal_allocators{}); } else { _Alproxy_ty _Alproxy(_Al); _Alproxy_ty _Right_alproxy(_Right_al); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Right_alproxy, _Leave_proxy_unbound{}); _Tidy(); _Pocma(_Al, _Right_al); _Proxy._Bind(_Alproxy, _STD addressof(_Get_data())); _Take_contents(_Right); } } void _Move_assign(deque& _Right, _No_propagate_allocators) { if (_Getal() == _Right._Getal()) { _Move_assign(_Right, _Equal_allocators{}); } else { assign( _STD make_move_iterator(_Right._Unchecked_begin()), _STD make_move_iterator(_Right._Unchecked_end())); } } public: deque& operator=(deque&& _Right) noexcept(_Alty_traits::is_always_equal::value) { if (this != _STD addressof(_Right)) { _Move_assign(_Right, _Choose_pocma<_Alty>{}); } return *this; } private: void _Take_contents(deque& _Right) noexcept { // move from _Right, stealing its contents // pre: _Getal() == _Right._Getal() auto& _My_data = _Get_data(); auto& _Right_data = _Right._Get_data(); _My_data._Swap_proxy_and_iterators(_Right_data); _My_data._Map = _Right_data._Map; _My_data._Mapsize = _Right_data._Mapsize; _My_data._Myoff = _Right_data._Myoff; _My_data._Mysize = _Right_data._Mysize; _Right_data._Map = nullptr; _Right_data._Mapsize = 0; _Right_data._Myoff = 0; _Right_data._Mysize = 0; } public: void push_front(_Ty&& _Val) { _Orphan_all(); _PUSH_FRONT_BEGIN; _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD move(_Val)); _PUSH_FRONT_END; } void push_back(_Ty&& _Val) { _Orphan_all(); _Emplace_back_internal(_STD move(_Val)); } iterator insert(const_iterator _Where, _Ty&& _Val) { return emplace(_Where, _STD move(_Val)); } template decltype(auto) emplace_front(_Valty&&... _Val) { _Orphan_all(); _PUSH_FRONT_BEGIN; _Alty_traits::construct( _Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD forward<_Valty>(_Val)...); _PUSH_FRONT_END; #if _HAS_CXX17 return front(); #endif // _HAS_CXX17 } template decltype(auto) emplace_back(_Valty&&... _Val) { _Orphan_all(); _PUSH_BACK_BEGIN; _Alty_traits::construct( _Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD forward<_Valty>(_Val)...); _PUSH_BACK_END; #if _HAS_CXX17 return back(); #endif // _HAS_CXX17 } template iterator emplace(const_iterator _Where, _Valty&&... _Val) { const auto _Off = static_cast(_Where - begin()); #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_Off <= _Mysize(), "deque emplace iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Off <= _Mysize() / 2) { // closer to front, push to front then rotate emplace_front(_STD forward<_Valty>(_Val)...); _STD rotate(begin(), begin() + 1, begin() + static_cast(1 + _Off)); } else { // closer to back, push to back then rotate emplace_back(_STD forward<_Valty>(_Val)...); _STD rotate(begin() + static_cast(_Off), end() - 1, end()); } return begin() + static_cast(_Off); } deque(initializer_list<_Ty> _Ilist, const _Alloc& _Al = allocator_type()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Alproxy_ty _Alproxy(_Getal()); _Container_proxy_ptr12<_Alproxy_ty> _Proxy(_Alproxy, _Get_data()); _Construct(_Ilist.begin(), _Ilist.end()); _Proxy._Release(); } deque& operator=(initializer_list<_Ty> _Ilist) { assign(_Ilist.begin(), _Ilist.end()); return *this; } void assign(initializer_list<_Ty> _Ilist) { assign(_Ilist.begin(), _Ilist.end()); } iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { return insert(_Where, _Ilist.begin(), _Ilist.end()); } ~deque() noexcept { _Tidy(); _Alproxy_ty _Proxy_allocator(_Getal()); _Delete_plain_internal(_Proxy_allocator, _STD exchange(_Get_data()._Myproxy, nullptr)); } void _Copy_assign(const deque& _Right, false_type) { _Pocca(_Getal(), _Right._Getal()); assign(_Right._Unchecked_begin(), _Right._Unchecked_end()); } void _Copy_assign(const deque& _Right, true_type) { if (_Getal() != _Right._Getal()) { _Tidy(); _Get_data()._Reload_proxy(static_cast<_Alproxy_ty>(_Getal()), static_cast<_Alproxy_ty>(_Right._Getal())); } _Copy_assign(_Right, false_type{}); } deque& operator=(const deque& _Right) { if (this != _STD addressof(_Right)) { _Copy_assign(_Right, _Choose_pocca<_Alty>{}); } return *this; } _NODISCARD iterator begin() noexcept { return iterator(_Myoff(), _STD addressof(_Get_data())); } _NODISCARD const_iterator begin() const noexcept { return const_iterator(_Myoff(), _STD addressof(_Get_data())); } _NODISCARD iterator end() noexcept { return iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } _NODISCARD const_iterator end() const noexcept { return const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } _Unchecked_iterator _Unchecked_begin() noexcept { return _Unchecked_iterator(_Myoff(), _STD addressof(_Get_data())); } _Unchecked_const_iterator _Unchecked_begin() const noexcept { return _Unchecked_const_iterator(_Myoff(), _STD addressof(_Get_data())); } _Unchecked_iterator _Unchecked_end() noexcept { return _Unchecked_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } _Unchecked_const_iterator _Unchecked_end() const noexcept { return _Unchecked_const_iterator(_Myoff() + _Mysize(), _STD addressof(_Get_data())); } iterator _Make_iter(const_iterator _Where) const noexcept { return iterator(_Where._Myoff, _STD addressof(_Get_data())); } _NODISCARD reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } _NODISCARD const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } _NODISCARD reverse_iterator rend() noexcept { return reverse_iterator(begin()); } _NODISCARD const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } _NODISCARD const_iterator cbegin() const noexcept { return begin(); } _NODISCARD const_iterator cend() const noexcept { return end(); } _NODISCARD const_reverse_iterator crbegin() const noexcept { return rbegin(); } _NODISCARD const_reverse_iterator crend() const noexcept { return rend(); } void shrink_to_fit() { size_type _Oldcapacity = _DEQUESIZ * _Mapsize(); size_type _Newcapacity = _Oldcapacity / 2; if (_Newcapacity < _DEQUESIZ * _DEQUEMAPSIZ) _Newcapacity = _DEQUESIZ * _DEQUEMAPSIZ; if ((empty() && 0 < _Mapsize()) || (!empty() && size() <= _Newcapacity && _Newcapacity < _Oldcapacity)) { // worth shrinking, do it deque _Tmp(_STD make_move_iterator(begin()), _STD make_move_iterator(end())); swap(_Tmp); } } void resize(_CRT_GUARDOVERFLOW size_type _Newsize) { while (_Mysize() < _Newsize) { emplace_back(); } while (_Newsize < _Mysize()) { pop_back(); } } void resize(_CRT_GUARDOVERFLOW size_type _Newsize, const _Ty& _Val) { _Orphan_all(); while (_Mysize() < _Newsize) { _Emplace_back_internal(_Val); } while (_Newsize < _Mysize()) { pop_back(); } } _NODISCARD size_type size() const noexcept { return _Mysize(); } _NODISCARD size_type max_size() const noexcept { return (_STD min)( static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } _NODISCARD bool empty() const noexcept { return _Mysize() == 0; } _NODISCARD allocator_type get_allocator() const noexcept { return static_cast(_Getal()); } _NODISCARD const_reference at(size_type _Pos) const { if (_Mysize() <= _Pos) _Xran(); return *(begin() + static_cast(_Pos)); } _NODISCARD reference at(size_type _Pos) { if (_Mysize() <= _Pos) { _Xran(); } return *(begin() + static_cast(_Pos)); } _NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *(_Unchecked_begin() + static_cast(_Pos)); } _NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *(_Unchecked_begin() + static_cast(_Pos)); } _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "front() called on empty deque"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Unchecked_begin(); } _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "front() called on empty deque"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Unchecked_begin(); } _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "back() called on empty deque"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *(_Unchecked_end() - 1); } _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "back() called on empty deque"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *(_Unchecked_end() - 1); } void push_front(const _Ty& _Val) { _Orphan_all(); _PUSH_FRONT_BEGIN; _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _Val); _PUSH_FRONT_END; } void pop_front() noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL == 2 if (empty()) { _STL_REPORT_ERROR("deque empty before pop"); } else { // something to erase, do it _Orphan_off(_Myoff()); size_type _Block = _Getblock(_Myoff()); _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _DEQUESIZ)); if (--_Mysize() == 0) { _Myoff() = 0; } else { ++_Myoff(); } } #else // _ITERATOR_DEBUG_LEVEL == 2 size_type _Block = _Getblock(_Myoff()); _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Myoff() % _DEQUESIZ)); if (--_Mysize() == 0) { _Myoff() = 0; } else { ++_Myoff(); } #endif // _ITERATOR_DEBUG_LEVEL == 2 } private: template void _Emplace_back_internal(_Tys&&... _Vals) { _PUSH_BACK_BEGIN; _Alty_traits::construct(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ), _STD forward<_Tys>(_Vals)...); _PUSH_BACK_END; } public: void push_back(const _Ty& _Val) { _Orphan_all(); _Emplace_back_internal(_Val); } void pop_back() noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL == 2 if (empty()) { _STL_REPORT_ERROR("deque empty before pop"); } else { // something to erase, do it size_type _Newoff = _Myoff() + _Mysize() - 1; _Orphan_off(_Newoff); size_type _Block = _Getblock(_Newoff); _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ)); if (--_Mysize() == 0) { _Myoff() = 0; } } #else // _ITERATOR_DEBUG_LEVEL == 2 size_type _Newoff = _Myoff() + _Mysize() - 1; size_type _Block = _Getblock(_Newoff); _Alty_traits::destroy(_Getal(), _Unfancy(_Map()[_Block] + _Newoff % _DEQUESIZ)); if (--_Mysize() == 0) { _Myoff() = 0; } #endif // _ITERATOR_DEBUG_LEVEL == 2 } template , int> = 0> void assign(_Iter _First, _Iter _Last) { _Orphan_all(); _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); auto _Myfirst = _Unchecked_begin(); const auto _Mylast = _Unchecked_end(); for (; _UFirst != _ULast; ++_UFirst) { // try to assign over an element in the container if (_Myfirst == _Mylast) { // container wasn't big enough, insert what's left at end do { emplace_back(*_UFirst); ++_UFirst; } while (_UFirst != _ULast); return; } *_Myfirst = *_UFirst; ++_Myfirst; } _Erase_last_n(static_cast(_Mylast - _Myfirst)); } void assign(_CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { // assign _Count * _Val _Orphan_all(); auto _Myfirst = _Unchecked_begin(); const auto _Oldsize = _Mysize(); auto _Assign_count = (_STD min)(_Count, _Oldsize); for (; 0 < _Assign_count; --_Assign_count) { *_Myfirst = _Val; ++_Myfirst; } const auto _Shrink_by = _Oldsize - _Assign_count; auto _Extend_by = _Count - _Assign_count; _Erase_last_n(_Shrink_by); for (; 0 < _Extend_by; --_Extend_by) { _Emplace_back_internal(_Val); } } iterator insert(const_iterator _Where, const _Ty& _Val) { size_type _Off = static_cast(_Where - begin()); #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_Off <= _Mysize(), "deque insert iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Off <= _Mysize() / 2) { // closer to front, push to front then copy push_front(_Val); _STD rotate(begin(), begin() + 1, begin() + static_cast(1 + _Off)); } else { // closer to back, push to back then copy push_back(_Val); _STD rotate(begin() + static_cast(_Off), end() - 1, end()); } return begin() + static_cast(_Off); } iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where size_type _Off = static_cast(_Where - begin()); _Insert_n(_Where, _Count, _Val); return begin() + static_cast(_Off); } template , int> = 0> iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { // insert [_First, _Last) at _Where, input iterators size_type _Off = static_cast(_Where - begin()); #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_Mysize() >= _Off, "deque insert iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); size_type _Oldsize = _Mysize(); if (_UFirst != _ULast) { if (_Off <= _Mysize() / 2) { // closer to front, push to front then rotate _TRY_BEGIN for (; _UFirst != _ULast; ++_UFirst) { emplace_front(*_UFirst); // prepend flipped } _CATCH_ALL while (_Oldsize < _Mysize()) { pop_front(); // restore old size, at least } _RERAISE; _CATCH_END size_type _Num = _Mysize() - _Oldsize; _STD reverse(begin(), begin() + static_cast(_Num)); // flip new stuff in place _STD rotate(begin(), begin() + static_cast(_Num), begin() + static_cast(_Num + _Off)); } else { // closer to back _TRY_BEGIN _Orphan_all(); for (; _UFirst != _ULast; ++_UFirst) { _Emplace_back_internal(*_UFirst); } _CATCH_ALL while (_Oldsize < _Mysize()) { pop_back(); // restore old size, at least } _RERAISE; _CATCH_END _STD rotate(begin() + static_cast(_Off), begin() + static_cast(_Oldsize), end()); } } return begin() + static_cast(_Off); } iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v) /* strengthened */ { return erase(_Where, _Where + 1); } iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept( is_nothrow_move_assignable_v) /* strengthened */ { iterator _First = _Make_iter(_First_arg); iterator _Last = _Make_iter(_Last_arg); #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_First <= _Last && begin() <= _First && _Last <= end(), "deque erase iterator outside range"); _Adl_verify_range(_First, _Last); auto _Off = static_cast(_First - begin()); auto _Count = static_cast(_Last - _First); bool _Moved = 0 < _Off && _Off + _Count < _Mysize(); #else // _ITERATOR_DEBUG_LEVEL == 2 auto _Off = static_cast(_First - begin()); auto _Count = static_cast(_Last - _First); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Off < static_cast(end() - _Last)) { // closer to front _STD move_backward(begin(), _First, _Last); // copy over hole for (; 0 < _Count; --_Count) { pop_front(); // pop copied elements } } else { // closer to back _STD move(_Last, end(), _First); // copy over hole for (; 0 < _Count; --_Count) { pop_back(); // pop copied elements } } #if _ITERATOR_DEBUG_LEVEL == 2 if (_Moved) { _Orphan_all(); } #endif // _ITERATOR_DEBUG_LEVEL == 2 return begin() + static_cast(_Off); } private: void _Erase_last_n(size_type _Count) noexcept { for (; 0 < _Count; --_Count) { pop_back(); } } public: void clear() noexcept { // erase all _Tidy(); } void swap(deque& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { _Pocs(_Getal(), _Right._Getal()); auto& _My_data = _Get_data(); auto& _Right_data = _Right._Get_data(); _My_data._Swap_proxy_and_iterators(_Right_data); _Swap_adl(_My_data._Map, _Right_data._Map); _STD swap(_My_data._Mapsize, _Right_data._Mapsize); _STD swap(_My_data._Myoff, _Right_data._Myoff); _STD swap(_My_data._Mysize, _Right_data._Mysize); } } private: void _Insert_n(const_iterator _Where, size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where iterator _Mid; size_type _Num; size_type _Off = static_cast(_Where - begin()); size_type _Oldsize = _Mysize(); size_type _Rem = _Oldsize - _Off; #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_Off <= _Oldsize, "deque insert iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Off < _Rem) { // closer to front _TRY_BEGIN if (_Off < _Count) { // insert longer than prefix for (_Num = _Count - _Off; 0 < _Num; --_Num) { push_front(_Val); // push excess values } for (_Num = _Off; 0 < _Num; --_Num) { push_front(begin()[static_cast(_Count - 1)]); // push prefix } _Mid = begin() + static_cast(_Count); _STD fill(_Mid, _Mid + static_cast(_Off), _Val); // fill in rest of values } else { // insert not longer than prefix for (_Num = _Count; 0 < _Num; --_Num) { push_front(begin()[static_cast(_Count - 1)]); // push part of prefix } _Mid = begin() + static_cast(_Count); _Alloc_temporary<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence _STD move(_Mid + static_cast(_Count), _Mid + static_cast(_Off), _Mid); // copy rest of prefix _STD fill(begin() + static_cast(_Off), _Mid + static_cast(_Off), _Tmp._Storage._Value); // fill in values } _CATCH_ALL while (_Oldsize < _Mysize()) { pop_front(); // restore old size, at least } _RERAISE; _CATCH_END } else { // closer to back _TRY_BEGIN if (_Rem < _Count) { // insert longer than suffix _Orphan_all(); for (_Num = _Count - _Rem; 0 < _Num; --_Num) { _Emplace_back_internal(_Val); // push excess values } for (_Num = 0; _Num < _Rem; ++_Num) { _Emplace_back_internal(begin()[static_cast(_Off + _Num)]); // push suffix } _Mid = begin() + static_cast(_Off); _STD fill(_Mid, _Mid + static_cast(_Rem), _Val); // fill in rest of values } else { // insert not longer than prefix for (_Num = 0; _Num < _Count; ++_Num) { _Emplace_back_internal( begin()[static_cast(_Off + _Rem - _Count + _Num)]); // push part of prefix } _Mid = begin() + static_cast(_Off); _Alloc_temporary<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence _STD move_backward(_Mid, _Mid + static_cast(_Rem - _Count), _Mid + static_cast(_Rem)); // copy rest of prefix _STD fill(_Mid, _Mid + static_cast(_Count), _Tmp._Storage._Value); // fill in values } _CATCH_ALL _Erase_last_n(_Mysize() - _Oldsize); _RERAISE; _CATCH_END } } [[noreturn]] void _Xlen() const { _Xlength_error("deque too long"); } [[noreturn]] void _Xran() const { _Xout_of_range("invalid deque subscript"); } void _Growmap(size_type _Count) { // grow map by at least _Count pointers, _Mapsize() a power of 2 static_assert(1 < _DEQUEMAPSIZ, "The _Xlen() test should always be performed."); _Alpty _Almap(_Getal()); size_type _Newsize = 0 < _Mapsize() ? _Mapsize() : 1; while (_Newsize - _Mapsize() < _Count || _Newsize < _DEQUEMAPSIZ) { // scale _Newsize to 2^N >= _Mapsize() + _Count if (max_size() / _DEQUESIZ - _Newsize < _Newsize) { _Xlen(); // result too long } _Newsize *= 2; } _Count = _Newsize - _Mapsize(); size_type _Myboff = _Myoff() / _DEQUESIZ; _Mapptr _Newmap = _Almap.allocate(_Mapsize() + _Count); _Mapptr _Myptr = _Newmap + _Myboff; _Myptr = _STD uninitialized_copy(_Map() + _Myboff, _Map() + _Mapsize(), _Myptr); // copy initial to end if (_Myboff <= _Count) { // increment greater than offset of initial block _Myptr = _STD uninitialized_copy(_Map(), _Map() + _Myboff, _Myptr); // copy rest of old _Uninitialized_value_construct_n_unchecked1(_Myptr, _Count - _Myboff); // clear suffix of new _Uninitialized_value_construct_n_unchecked1(_Newmap, _Myboff); // clear prefix of new } else { // increment not greater than offset of initial block _STD uninitialized_copy(_Map(), _Map() + _Count, _Myptr); // copy more old _Myptr = _STD uninitialized_copy(_Map() + _Count, _Map() + _Myboff, _Newmap); // copy rest of old _Uninitialized_value_construct_n_unchecked1(_Myptr, _Count); // clear rest to initial block } _Destroy_range(_Map() + _Myboff, _Map() + _Mapsize()); if (_Map() != _Mapptr()) { _Almap.deallocate(_Map(), _Mapsize()); // free storage for old } _Map() = _Newmap; // point at new _Mapsize() += _Count; } void _Tidy() noexcept { // free all storage _Orphan_all(); _Alpty _Almap(_Getal()); while (!empty()) { pop_back(); } for (size_type _Block = _Mapsize(); 0 < _Block;) { // free storage for a block and destroy pointer if (_Map()[--_Block]) { // free block and destroy its pointer _Getal().deallocate(_Map()[_Block], _DEQUESIZ); _Destroy_in_place(_Map()[_Block]); } } if (_Map() != _Mapptr()) { _Almap.deallocate(_Map(), _Mapsize()); // free storage for map } _Mapsize() = 0; _Map() = _Mapptr(); } #if _ITERATOR_DEBUG_LEVEL == 2 void _Orphan_off(size_type _Offlo) const noexcept { // orphan iterators with specified offset(s) size_type _Offhigh = _Myoff() + _Mysize() <= _Offlo + 1 ? static_cast(-1) : _Offlo; if (_Offlo == _Myoff()) { _Offlo = 0; } _Lockit _Lock(_LOCK_DEBUG); _Iterator_base12** _Pnext = &_Get_data()._Myproxy->_Myfirstiter; while (*_Pnext) { const auto _Pnextoff = static_cast(**_Pnext)._Myoff; if (_Pnextoff < _Offlo || _Offhigh < _Pnextoff) { _Pnext = &(*_Pnext)->_Mynextiter; } else { // orphan the iterator (*_Pnext)->_Myproxy = nullptr; *_Pnext = (*_Pnext)->_Mynextiter; } } } #endif // _ITERATOR_DEBUG_LEVEL == 2 size_type _Getblock(size_type _Off) const noexcept { return _Get_data()._Getblock(_Off); } void _Orphan_all() noexcept { _Get_data()._Orphan_all(); } _Alty& _Getal() noexcept { return _Mypair._Get_first(); } const _Alty& _Getal() const noexcept { return _Mypair._Get_first(); } _Scary_val& _Get_data() noexcept { return _Mypair._Myval2; } const _Scary_val& _Get_data() const noexcept { return _Mypair._Myval2; } _Mapptr& _Map() noexcept { return _Get_data()._Map; } const _Mapptr& _Map() const noexcept { return _Get_data()._Map; } size_type& _Mapsize() noexcept { return _Get_data()._Mapsize; } const size_type& _Mapsize() const noexcept { return _Get_data()._Mapsize; } size_type& _Myoff() noexcept { return _Get_data()._Myoff; } const size_type& _Myoff() const noexcept { return _Get_data()._Myoff; } size_type& _Mysize() noexcept { return _Get_data()._Mysize; } const size_type& _Mysize() const noexcept { return _Get_data()._Mysize; } _Compressed_pair<_Alty, _Scary_val> _Mypair; }; #if _HAS_CXX17 template >, enable_if_t, _Is_allocator<_Alloc>>, int> = 0> deque(_Iter, _Iter, _Alloc = _Alloc()) -> deque<_Iter_value_t<_Iter>, _Alloc>; #endif // _HAS_CXX17 template void swap(deque<_Ty, _Alloc>& _Left, deque<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { _Left.swap(_Right); } template _NODISCARD bool operator==(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return _Left.size() == _Right.size() && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); } template _NODISCARD bool operator!=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return !(_Left == _Right); } template _NODISCARD bool operator<(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return _STD lexicographical_compare( _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); } template _NODISCARD bool operator<=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return !(_Right < _Left); } template _NODISCARD bool operator>(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return _Right < _Left; } template _NODISCARD bool operator>=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } #if _HAS_CXX20 template typename deque<_Ty, _Alloc>::size_type erase(deque<_Ty, _Alloc>& _Cont, const _Uty& _Val) { return _Erase_remove(_Cont, _Val); } template typename deque<_Ty, _Alloc>::size_type erase_if(deque<_Ty, _Alloc>& _Cont, _Pr _Pred) { return _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } #endif // _HAS_CXX20 #if _HAS_CXX17 namespace pmr { template using deque = _STD deque<_Ty, polymorphic_allocator<_Ty>>; } // namespace pmr #endif // _HAS_CXX17 _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) #endif // _STL_COMPILER_PREPROCESSOR #endif // _DEQUE_