зеркало из https://github.com/microsoft/STL.git
1636 строки
58 KiB
C++
1636 строки
58 KiB
C++
// deque standard header
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#pragma once
|
|
#ifndef _DEQUE_
|
|
#define _DEQUE_
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <xmemory>
|
|
|
|
#if _HAS_CXX17
|
|
#include <xpolymorphic_allocator.h>
|
|
#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 _Mydeque>
|
|
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<const _Mydeque*>(_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>::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<difference_type>(_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 <class _Mydeque>
|
|
_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 _Mydeque>
|
|
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<reference>(_Mybase::operator*());
|
|
}
|
|
|
|
_NODISCARD pointer operator->() const {
|
|
return pointer_traits<pointer>::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<reference>(_Mybase::operator[](_Off));
|
|
}
|
|
};
|
|
|
|
template <class _Mydeque>
|
|
_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 _Mydeque>
|
|
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<const _Mydeque*>(_Pdeque));
|
|
}
|
|
|
|
_NODISCARD reference operator*() const {
|
|
const auto _Mycont = static_cast<const _Mydeque*>(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>::pointer_to(**this);
|
|
}
|
|
|
|
_Deque_const_iterator& operator++() {
|
|
#if _ITERATOR_DEBUG_LEVEL != 0
|
|
const auto _Mycont = static_cast<const _Mydeque*>(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<const _Mydeque*>(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<const _Mydeque*>(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<difference_type>(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<const _Mydeque*>(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 <class _Mydeque>
|
|
_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 _Mydeque>
|
|
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<reference>(_Mybase::operator*());
|
|
}
|
|
|
|
_NODISCARD pointer operator->() const {
|
|
return pointer_traits<pointer>::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<reference>(_Mybase::operator[](_Off));
|
|
}
|
|
|
|
using _Prevent_inheriting_unwrap = _Deque_iterator;
|
|
|
|
_NODISCARD _Deque_unchecked_iterator<_Mydeque> _Unwrapped() const {
|
|
return {this->_Myoff, this->_Getcont()};
|
|
}
|
|
};
|
|
|
|
template <class _Mydeque>
|
|
_NODISCARD _Deque_iterator<_Mydeque> operator+(
|
|
typename _Deque_iterator<_Mydeque>::difference_type _Off, _Deque_iterator<_Mydeque> _Next) {
|
|
return _Next += _Off;
|
|
}
|
|
|
|
// deque TYPE WRAPPERS
|
|
template <class _Value_type, class _Size_type, class _Difference_type, class _Pointer, class _Const_pointer,
|
|
class _Reference, class _Const_reference, class _Mapptr_type>
|
|
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 <class _Ty>
|
|
struct _Deque_simple_types : _Simple_types<_Ty> {
|
|
using _Mapptr = _Ty**;
|
|
};
|
|
|
|
// CLASS TEMPLATE _Deque_val
|
|
template <class _Val_types>
|
|
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 _Ty, class _Alloc = allocator<_Ty>>
|
|
class deque {
|
|
private:
|
|
friend _Tidy_guard<deque>;
|
|
static_assert(!_ENFORCE_MATCHING_ALLOCATORS || is_same_v<_Ty, typename _Alloc::value_type>,
|
|
_MISMATCHED_ALLOCATOR_MESSAGE("deque<T, Allocator>", "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<conditional_t<_Is_simple_alloc_v<_Alty>, _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<iterator>;
|
|
using const_reverse_iterator = _STD reverse_iterator<const_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 <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, 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 <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, 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 <class _Iter>
|
|
void _Construct(_Iter _First, _Iter _Last) { // initialize from [_First, _Last), input iterators
|
|
_Tidy_guard<deque> _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<deque> _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 <class... _Valty>
|
|
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 <class... _Valty>
|
|
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 <class... _Valty>
|
|
iterator emplace(const_iterator _Where, _Valty&&... _Val) {
|
|
const auto _Off = static_cast<size_type>(_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<difference_type>(1 + _Off));
|
|
} else { // closer to back, push to back then rotate
|
|
emplace_back(_STD forward<_Valty>(_Val)...);
|
|
_STD rotate(begin() + static_cast<difference_type>(_Off), end() - 1, end());
|
|
}
|
|
return begin() + static_cast<difference_type>(_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<size_type>((numeric_limits<difference_type>::max)()), _Alty_traits::max_size(_Getal()));
|
|
}
|
|
|
|
_NODISCARD bool empty() const noexcept {
|
|
return _Mysize() == 0;
|
|
}
|
|
|
|
_NODISCARD allocator_type get_allocator() const noexcept {
|
|
return static_cast<allocator_type>(_Getal());
|
|
}
|
|
|
|
_NODISCARD const_reference at(size_type _Pos) const {
|
|
if (_Mysize() <= _Pos)
|
|
_Xran();
|
|
return *(begin() + static_cast<difference_type>(_Pos));
|
|
}
|
|
|
|
_NODISCARD reference at(size_type _Pos) {
|
|
if (_Mysize() <= _Pos) {
|
|
_Xran();
|
|
}
|
|
|
|
return *(begin() + static_cast<difference_type>(_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<difference_type>(_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<difference_type>(_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 <class... _Tys>
|
|
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 <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, 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<size_type>(_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<size_type>(_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<difference_type>(1 + _Off));
|
|
} else { // closer to back, push to back then copy
|
|
push_back(_Val);
|
|
_STD rotate(begin() + static_cast<difference_type>(_Off), end() - 1, end());
|
|
}
|
|
|
|
return begin() + static_cast<difference_type>(_Off);
|
|
}
|
|
|
|
iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const _Ty& _Val) {
|
|
// insert _Count * _Val at _Where
|
|
size_type _Off = static_cast<size_type>(_Where - begin());
|
|
_Insert_n(_Where, _Count, _Val);
|
|
return begin() + static_cast<difference_type>(_Off);
|
|
}
|
|
|
|
template <class _Iter, enable_if_t<_Is_iterator_v<_Iter>, int> = 0>
|
|
iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) {
|
|
// insert [_First, _Last) at _Where, input iterators
|
|
size_type _Off = static_cast<size_type>(_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<difference_type>(_Num)); // flip new stuff in place
|
|
_STD rotate(begin(), begin() + static_cast<difference_type>(_Num),
|
|
begin() + static_cast<difference_type>(_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<difference_type>(_Off),
|
|
begin() + static_cast<difference_type>(_Oldsize), end());
|
|
}
|
|
}
|
|
|
|
return begin() + static_cast<difference_type>(_Off);
|
|
}
|
|
|
|
iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v<value_type>) /* strengthened */ {
|
|
return erase(_Where, _Next_iter(_Where));
|
|
}
|
|
|
|
iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept(
|
|
is_nothrow_move_assignable_v<value_type>) /* 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<size_type>(_First - begin());
|
|
auto _Count = static_cast<size_type>(_Last - _First);
|
|
bool _Moved = 0 < _Off && _Off + _Count < _Mysize();
|
|
|
|
#else // _ITERATOR_DEBUG_LEVEL == 2
|
|
auto _Off = static_cast<size_type>(_First - begin());
|
|
auto _Count = static_cast<size_type>(_Last - _First);
|
|
#endif // _ITERATOR_DEBUG_LEVEL == 2
|
|
|
|
if (_Off < static_cast<size_type>(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<difference_type>(_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<size_type>(_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<difference_type>(_Count - 1)]); // push prefix
|
|
}
|
|
|
|
_Mid = begin() + static_cast<difference_type>(_Count);
|
|
_STD fill(_Mid, _Mid + static_cast<difference_type>(_Off), _Val); // fill in rest of values
|
|
} else { // insert not longer than prefix
|
|
for (_Num = _Count; 0 < _Num; --_Num) {
|
|
push_front(begin()[static_cast<difference_type>(_Count - 1)]); // push part of prefix
|
|
}
|
|
|
|
_Mid = begin() + static_cast<difference_type>(_Count);
|
|
_Alloc_temporary<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence
|
|
_STD move(_Mid + static_cast<difference_type>(_Count), _Mid + static_cast<difference_type>(_Off),
|
|
_Mid); // copy rest of prefix
|
|
_STD fill(begin() + static_cast<difference_type>(_Off), _Mid + static_cast<difference_type>(_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<difference_type>(_Off + _Num)]); // push suffix
|
|
}
|
|
|
|
_Mid = begin() + static_cast<difference_type>(_Off);
|
|
_STD fill(_Mid, _Mid + static_cast<difference_type>(_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<difference_type>(_Off + _Rem - _Count + _Num)]); // push part of prefix
|
|
}
|
|
|
|
_Mid = begin() + static_cast<difference_type>(_Off);
|
|
_Alloc_temporary<_Alty> _Tmp(_Getal(), _Val); // in case _Val is in sequence
|
|
_STD move_backward(_Mid, _Mid + static_cast<difference_type>(_Rem - _Count),
|
|
_Mid + static_cast<difference_type>(_Rem)); // copy rest of prefix
|
|
_STD fill(_Mid, _Mid + static_cast<difference_type>(_Count),
|
|
_Tmp._Storage._Value); // fill in values
|
|
}
|
|
_CATCH_ALL
|
|
_Erase_last_n(_Mysize() - _Oldsize);
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
}
|
|
|
|
[[noreturn]] void _Xlen() const {
|
|
_Xlength_error("deque<T> too long");
|
|
}
|
|
|
|
[[noreturn]] void _Xran() const {
|
|
_Xout_of_range("invalid deque<T> 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<size_type>(-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<const_iterator&>(**_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 <class _Iter, class _Alloc = allocator<_Iter_value_t<_Iter>>,
|
|
enable_if_t<conjunction_v<_Is_iterator<_Iter>, _Is_allocator<_Alloc>>, int> = 0>
|
|
deque(_Iter, _Iter, _Alloc = _Alloc()) -> deque<_Iter_value_t<_Iter>, _Alloc>;
|
|
#endif // _HAS_CXX17
|
|
|
|
template <class _Ty, class _Alloc>
|
|
void swap(deque<_Ty, _Alloc>& _Left, deque<_Ty, _Alloc>& _Right) noexcept /* strengthened */ {
|
|
_Left.swap(_Right);
|
|
}
|
|
|
|
template <class _Ty, class _Alloc>
|
|
_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 <class _Ty, class _Alloc>
|
|
_NODISCARD bool operator!=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) {
|
|
return !(_Left == _Right);
|
|
}
|
|
|
|
template <class _Ty, class _Alloc>
|
|
_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 <class _Ty, class _Alloc>
|
|
_NODISCARD bool operator<=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) {
|
|
return !(_Right < _Left);
|
|
}
|
|
|
|
template <class _Ty, class _Alloc>
|
|
_NODISCARD bool operator>(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) {
|
|
return _Right < _Left;
|
|
}
|
|
|
|
template <class _Ty, class _Alloc>
|
|
_NODISCARD bool operator>=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) {
|
|
return !(_Left < _Right);
|
|
}
|
|
|
|
#if _HAS_CXX20
|
|
template <class _Ty, class _Alloc, class _Uty>
|
|
typename deque<_Ty, _Alloc>::size_type erase(deque<_Ty, _Alloc>& _Cont, const _Uty& _Val) {
|
|
return _Erase_remove(_Cont, _Val);
|
|
}
|
|
|
|
template <class _Ty, class _Alloc, class _Pr>
|
|
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 <class _Ty>
|
|
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_
|