| // Deque implementation (out of line) -*- C++ -*- | |
| // Copyright (C) 2001-2026 Free Software Foundation, Inc. | |
| // | |
| // This file is part of the GNU ISO C++ Library. This library is free | |
| // software; you can redistribute it and/or modify it under the | |
| // terms of the GNU General Public License as published by the | |
| // Free Software Foundation; either version 3, or (at your option) | |
| // any later version. | |
| // This library is distributed in the hope that it will be useful, | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // GNU General Public License for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| /* | |
| * | |
| * Copyright (c) 1994 | |
| * Hewlett-Packard Company | |
| * | |
| * Permission to use, copy, modify, distribute and sell this software | |
| * and its documentation for any purpose is hereby granted without fee, | |
| * provided that the above copyright notice appear in all copies and | |
| * that both that copyright notice and this permission notice appear | |
| * in supporting documentation. Hewlett-Packard Company makes no | |
| * representations about the suitability of this software for any | |
| * purpose. It is provided "as is" without express or implied warranty. | |
| * | |
| * | |
| * Copyright (c) 1997 | |
| * Silicon Graphics Computer Systems, Inc. | |
| * | |
| * Permission to use, copy, modify, distribute and sell this software | |
| * and its documentation for any purpose is hereby granted without fee, | |
| * provided that the above copyright notice appear in all copies and | |
| * that both that copyright notice and this permission notice appear | |
| * in supporting documentation. Silicon Graphics makes no | |
| * representations about the suitability of this software for any | |
| * purpose. It is provided "as is" without express or implied warranty. | |
| */ | |
| /** @file bits/deque.tcc | |
| * This is an internal header file, included by other library headers. | |
| * Do not attempt to use it directly. @headername{deque} | |
| */ | |
| #ifndef _DEQUE_TCC | |
| #define _DEQUE_TCC 1 | |
| #include <bits/stl_algobase.h> | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| _GLIBCXX_BEGIN_NAMESPACE_CONTAINER | |
| #if __cplusplus >= 201103L | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_default_initialize() | |
| { | |
| _Map_pointer __cur; | |
| __try | |
| { | |
| for (__cur = this->_M_impl._M_start._M_node; | |
| __cur < this->_M_impl._M_finish._M_node; | |
| ++__cur) | |
| std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), | |
| _M_get_Tp_allocator()); | |
| std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, | |
| this->_M_impl._M_finish._M_cur, | |
| _M_get_Tp_allocator()); | |
| } | |
| __catch(...) | |
| { | |
| std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), | |
| _M_get_Tp_allocator()); | |
| __throw_exception_again; | |
| } | |
| } | |
| #endif | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| deque<_Tp, _Alloc>& | |
| deque<_Tp, _Alloc>:: | |
| operator=(const deque& __x) | |
| { | |
| if (std::__addressof(__x) != this) | |
| { | |
| #if __cplusplus >= 201103L | |
| if (_Alloc_traits::_S_propagate_on_copy_assign()) | |
| { | |
| if (!_Alloc_traits::_S_always_equal() | |
| && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) | |
| { | |
| // Replacement allocator cannot free existing storage, | |
| // so deallocate everything and take copy of __x's data. | |
| _M_replace_map(__x, __x.get_allocator()); | |
| std::__alloc_on_copy(_M_get_Tp_allocator(), | |
| __x._M_get_Tp_allocator()); | |
| return *this; | |
| } | |
| std::__alloc_on_copy(_M_get_Tp_allocator(), | |
| __x._M_get_Tp_allocator()); | |
| } | |
| #endif | |
| const size_type __len = size(); | |
| if (__len >= __x.size()) | |
| _M_erase_at_end(std::copy(__x.begin(), __x.end(), | |
| this->_M_impl._M_start)); | |
| else | |
| { | |
| const_iterator __mid = __x.begin() + difference_type(__len); | |
| std::copy(__x.begin(), __mid, this->_M_impl._M_start); | |
| _M_range_insert_aux(this->_M_impl._M_finish, __mid, __x.end(), | |
| std::random_access_iterator_tag()); | |
| } | |
| } | |
| return *this; | |
| } | |
| #if __cplusplus >= 201103L | |
| template<typename _Tp, typename _Alloc> | |
| template<typename... _Args> | |
| #if __cplusplus > 201402L | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::reference | |
| #else | |
| void | |
| #endif | |
| deque<_Tp, _Alloc>:: | |
| emplace_front(_Args&&... __args) | |
| { | |
| if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) | |
| { | |
| _Alloc_traits::construct(this->_M_impl, | |
| this->_M_impl._M_start._M_cur - 1, | |
| std::forward<_Args>(__args)...); | |
| --this->_M_impl._M_start._M_cur; | |
| } | |
| else | |
| _M_push_front_aux(std::forward<_Args>(__args)...); | |
| #if __cplusplus > 201402L | |
| return front(); | |
| #endif | |
| } | |
| template<typename _Tp, typename _Alloc> | |
| template<typename... _Args> | |
| #if __cplusplus > 201402L | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::reference | |
| #else | |
| void | |
| #endif | |
| deque<_Tp, _Alloc>:: | |
| emplace_back(_Args&&... __args) | |
| { | |
| if (this->_M_impl._M_finish._M_cur | |
| != this->_M_impl._M_finish._M_last - 1) | |
| { | |
| _Alloc_traits::construct(this->_M_impl, | |
| this->_M_impl._M_finish._M_cur, | |
| std::forward<_Args>(__args)...); | |
| ++this->_M_impl._M_finish._M_cur; | |
| } | |
| else | |
| _M_push_back_aux(std::forward<_Args>(__args)...); | |
| #if __cplusplus > 201402L | |
| return back(); | |
| #endif | |
| } | |
| #endif | |
| #if __cplusplus >= 201103L | |
| template<typename _Tp, typename _Alloc> | |
| template<typename... _Args> | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| emplace(const_iterator __position, _Args&&... __args) | |
| { | |
| if (__position._M_cur == this->_M_impl._M_start._M_cur) | |
| { | |
| emplace_front(std::forward<_Args>(__args)...); | |
| return this->_M_impl._M_start; | |
| } | |
| else if (__position._M_cur == this->_M_impl._M_finish._M_cur) | |
| { | |
| emplace_back(std::forward<_Args>(__args)...); | |
| iterator __tmp = this->_M_impl._M_finish; | |
| --__tmp; | |
| return __tmp; | |
| } | |
| else | |
| return _M_emplace_aux(__position._M_const_cast(), | |
| std::forward<_Args>(__args)...); | |
| } | |
| #endif | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| #if __cplusplus >= 201103L | |
| insert(const_iterator __position, const value_type& __x) | |
| #else | |
| insert(iterator __position, const value_type& __x) | |
| #endif | |
| { | |
| if (__position._M_cur == this->_M_impl._M_start._M_cur) | |
| { | |
| push_front(__x); | |
| return this->_M_impl._M_start; | |
| } | |
| else if (__position._M_cur == this->_M_impl._M_finish._M_cur) | |
| { | |
| push_back(__x); | |
| iterator __tmp = this->_M_impl._M_finish; | |
| --__tmp; | |
| return __tmp; | |
| } | |
| else | |
| return _M_insert_aux(__position._M_const_cast(), __x); | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| _M_erase(iterator __position) | |
| { | |
| iterator __next = __position; | |
| ++__next; | |
| const difference_type __index = __position - begin(); | |
| if (static_cast<size_type>(__index) < (size() >> 1)) | |
| { | |
| if (__position != begin()) | |
| _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next); | |
| pop_front(); | |
| } | |
| else | |
| { | |
| if (__next != end()) | |
| _GLIBCXX_MOVE3(__next, end(), __position); | |
| pop_back(); | |
| } | |
| return begin() + __index; | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| _M_erase(iterator __first, iterator __last) | |
| { | |
| if (__first == __last) | |
| return __first; | |
| else if (__first == begin() && __last == end()) | |
| { | |
| clear(); | |
| return end(); | |
| } | |
| else | |
| { | |
| const difference_type __n = __last - __first; | |
| const difference_type __elems_before = __first - begin(); | |
| if (static_cast<size_type>(__elems_before) <= (size() - __n) / 2) | |
| { | |
| if (__first != begin()) | |
| _GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last); | |
| _M_erase_at_begin(begin() + __n); | |
| } | |
| else | |
| { | |
| if (__last != end()) | |
| _GLIBCXX_MOVE3(__last, end(), __first); | |
| _M_erase_at_end(end() - __n); | |
| } | |
| return begin() + __elems_before; | |
| } | |
| } | |
| template <typename _Tp, class _Alloc> | |
| template <typename _InputIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_assign_aux(_InputIterator __first, _InputIterator __last, | |
| std::input_iterator_tag) | |
| { | |
| iterator __cur = begin(); | |
| for (; __first != __last && __cur != end(); ++__cur, (void)++__first) | |
| *__cur = *__first; | |
| if (__first == __last) | |
| _M_erase_at_end(__cur); | |
| else | |
| _M_range_insert_aux(end(), __first, __last, | |
| std::__iterator_category(__first)); | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) | |
| { | |
| if (__pos._M_cur == this->_M_impl._M_start._M_cur) | |
| { | |
| iterator __new_start = _M_reserve_elements_at_front(__n); | |
| __try | |
| { | |
| std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start, | |
| __x, _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(__new_start._M_node, | |
| this->_M_impl._M_start._M_node); | |
| __throw_exception_again; | |
| } | |
| } | |
| else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) | |
| { | |
| iterator __new_finish = _M_reserve_elements_at_back(__n); | |
| __try | |
| { | |
| std::__uninitialized_fill_a(this->_M_impl._M_finish, | |
| __new_finish, __x, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, | |
| __new_finish._M_node + 1); | |
| __throw_exception_again; | |
| } | |
| } | |
| else | |
| _M_insert_aux(__pos, __n, __x); | |
| } | |
| #if __cplusplus >= 201103L | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_default_append(size_type __n) | |
| { | |
| if (__n) | |
| { | |
| iterator __new_finish = _M_reserve_elements_at_back(__n); | |
| __try | |
| { | |
| std::__uninitialized_default_a(this->_M_impl._M_finish, | |
| __new_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, | |
| __new_finish._M_node + 1); | |
| __throw_exception_again; | |
| } | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR bool | |
| deque<_Tp, _Alloc>:: | |
| _M_shrink_to_fit() | |
| { | |
| const difference_type __front_capacity | |
| = (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first); | |
| if (__front_capacity == 0) | |
| return false; | |
| const difference_type __back_capacity | |
| = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); | |
| if (size_type(__front_capacity + __back_capacity) < _S_buffer_size()) | |
| return false; | |
| return std::__shrink_to_fit_aux<deque>::_S_do_it(*this); | |
| } | |
| #endif | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_fill_initialize(const value_type& __value) | |
| { | |
| _Map_pointer __cur; | |
| __try | |
| { | |
| for (__cur = this->_M_impl._M_start._M_node; | |
| __cur < this->_M_impl._M_finish._M_node; | |
| ++__cur) | |
| std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), | |
| __value, _M_get_Tp_allocator()); | |
| std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, | |
| this->_M_impl._M_finish._M_cur, | |
| __value, _M_get_Tp_allocator()); | |
| } | |
| __catch(...) | |
| { | |
| std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), | |
| _M_get_Tp_allocator()); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _InputIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_initialize(_InputIterator __first, _InputIterator __last, | |
| std::input_iterator_tag) | |
| { | |
| this->_M_initialize_map(0); | |
| __try | |
| { | |
| for (; __first != __last; ++__first) | |
| #if __cplusplus >= 201103L | |
| emplace_back(*__first); | |
| #else | |
| push_back(*__first); | |
| #endif | |
| } | |
| __catch(...) | |
| { | |
| clear(); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _ForwardIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, | |
| std::forward_iterator_tag) | |
| { | |
| const size_type __n = std::distance(__first, __last); | |
| this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); | |
| _Map_pointer __cur_node; | |
| __try | |
| { | |
| for (__cur_node = this->_M_impl._M_start._M_node; | |
| __cur_node < this->_M_impl._M_finish._M_node; | |
| ++__cur_node) | |
| { | |
| if (__n < _S_buffer_size()) | |
| __builtin_unreachable(); // See PR 100516 | |
| _ForwardIterator __mid = __first; | |
| std::advance(__mid, _S_buffer_size()); | |
| std::__uninitialized_copy_a(__first, __mid, *__cur_node, | |
| _M_get_Tp_allocator()); | |
| __first = __mid; | |
| } | |
| std::__uninitialized_copy_a(__first, __last, | |
| this->_M_impl._M_finish._M_first, | |
| _M_get_Tp_allocator()); | |
| } | |
| __catch(...) | |
| { | |
| std::_Destroy(this->_M_impl._M_start, | |
| iterator(*__cur_node, __cur_node), | |
| _M_get_Tp_allocator()); | |
| __throw_exception_again; | |
| } | |
| } | |
| // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1. | |
| template<typename _Tp, typename _Alloc> | |
| #if __cplusplus >= 201103L | |
| template<typename... _Args> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_push_back_aux(_Args&&... __args) | |
| #else | |
| void | |
| deque<_Tp, _Alloc>:: | |
| _M_push_back_aux(const value_type& __t) | |
| #endif | |
| { | |
| if (size() == max_size()) | |
| __throw_length_error( | |
| __N("cannot create std::deque larger than max_size()")); | |
| _M_reserve_map_at_back(); | |
| *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node(); | |
| __try | |
| { | |
| #if __cplusplus >= 201103L | |
| _Alloc_traits::construct(this->_M_impl, | |
| this->_M_impl._M_finish._M_cur, | |
| std::forward<_Args>(__args)...); | |
| #else | |
| this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t); | |
| #endif | |
| this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node | |
| + 1); | |
| this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first; | |
| } | |
| __catch(...) | |
| { | |
| _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1)); | |
| __throw_exception_again; | |
| } | |
| } | |
| // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first. | |
| template<typename _Tp, typename _Alloc> | |
| #if __cplusplus >= 201103L | |
| template<typename... _Args> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_push_front_aux(_Args&&... __args) | |
| #else | |
| void | |
| deque<_Tp, _Alloc>:: | |
| _M_push_front_aux(const value_type& __t) | |
| #endif | |
| { | |
| if (size() == max_size()) | |
| __throw_length_error( | |
| __N("cannot create std::deque larger than max_size()")); | |
| _M_reserve_map_at_front(); | |
| *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node(); | |
| __try | |
| { | |
| this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node | |
| - 1); | |
| this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1; | |
| #if __cplusplus >= 201103L | |
| _Alloc_traits::construct(this->_M_impl, | |
| this->_M_impl._M_start._M_cur, | |
| std::forward<_Args>(__args)...); | |
| #else | |
| this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t); | |
| #endif | |
| } | |
| __catch(...) | |
| { | |
| ++this->_M_impl._M_start; | |
| _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1)); | |
| __throw_exception_again; | |
| } | |
| } | |
| // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first. | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_pop_back_aux() | |
| { | |
| _M_deallocate_node(this->_M_impl._M_finish._M_first); | |
| this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1); | |
| this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1; | |
| _Alloc_traits::destroy(_M_get_Tp_allocator(), | |
| this->_M_impl._M_finish._M_cur); | |
| } | |
| // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1. | |
| // Note that if the deque has at least one element (a precondition for this | |
| // member function), and if | |
| // _M_impl._M_start._M_cur == _M_impl._M_start._M_last, | |
| // then the deque must have at least two nodes. | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_pop_front_aux() | |
| { | |
| _Alloc_traits::destroy(_M_get_Tp_allocator(), | |
| this->_M_impl._M_start._M_cur); | |
| _M_deallocate_node(this->_M_impl._M_start._M_first); | |
| this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1); | |
| this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first; | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _InputIterator, typename _Sentinel> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_prepend(_InputIterator __first, _Sentinel __last, | |
| size_type __n) | |
| { | |
| iterator __new_start = _M_reserve_elements_at_front(__n); | |
| __try | |
| { | |
| std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last, | |
| __new_start, _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(__new_start._M_node, | |
| this->_M_impl._M_start._M_node); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _InputIterator, typename _Sentinel> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_append(_InputIterator __first, _Sentinel __last, | |
| size_type __n) | |
| { | |
| iterator __new_finish = _M_reserve_elements_at_back(__n); | |
| __try | |
| { | |
| std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last, | |
| this->_M_impl._M_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, | |
| __new_finish._M_node + 1); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _InputIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_insert_aux(iterator __pos, | |
| _InputIterator __first, _InputIterator __last, | |
| std::input_iterator_tag) | |
| { std::copy(__first, __last, std::inserter(*this, __pos)); } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _ForwardIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_range_insert_aux(iterator __pos, | |
| _ForwardIterator __first, _ForwardIterator __last, | |
| std::forward_iterator_tag) | |
| { | |
| const size_type __n = std::distance(__first, __last); | |
| if (__builtin_expect(__n == 0, 0)) | |
| return; | |
| if (__pos._M_cur == this->_M_impl._M_start._M_cur) | |
| _M_range_prepend(__first, __last, __n); | |
| else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) | |
| _M_range_append(__first, __last, __n); | |
| else | |
| _M_insert_aux(__pos, __first, __last, __n); | |
| } | |
| template<typename _Tp, typename _Alloc> | |
| #if __cplusplus >= 201103L | |
| template<typename... _Args> | |
| _GLIBCXX26_CONSTEXPR | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| _M_emplace_aux(iterator __pos, _Args&&... __args) | |
| { | |
| // We should construct this temporary while the deque is | |
| // in its current state in case something in __args... | |
| // depends on that state before shuffling elements around. | |
| _Temporary_value __tmp(this, std::forward<_Args>(__args)...); | |
| #else | |
| typename deque<_Tp, _Alloc>::iterator | |
| deque<_Tp, _Alloc>:: | |
| _M_insert_aux(iterator __pos, const value_type& __x) | |
| { | |
| value_type __x_copy = __x; // XXX copy | |
| #endif | |
| difference_type __index = __pos - this->_M_impl._M_start; | |
| if (static_cast<size_type>(__index) < size() / 2) | |
| { | |
| push_front(_GLIBCXX_MOVE(front())); | |
| iterator __front1 = this->_M_impl._M_start; | |
| ++__front1; | |
| iterator __front2 = __front1; | |
| ++__front2; | |
| __pos = this->_M_impl._M_start + __index; | |
| iterator __pos1 = __pos; | |
| ++__pos1; | |
| _GLIBCXX_MOVE3(__front2, __pos1, __front1); | |
| } | |
| else | |
| { | |
| push_back(_GLIBCXX_MOVE(back())); | |
| iterator __back1 = this->_M_impl._M_finish; | |
| --__back1; | |
| iterator __back2 = __back1; | |
| --__back2; | |
| __pos = this->_M_impl._M_start + __index; | |
| _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1); | |
| } | |
| #if __cplusplus >= 201103L | |
| *__pos = std::move(__tmp._M_val()); | |
| #else | |
| *__pos = __x_copy; | |
| #endif | |
| return __pos; | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) | |
| { | |
| const difference_type __elems_before = __pos - this->_M_impl._M_start; | |
| const size_type __length = this->size(); | |
| value_type __x_copy = __x; | |
| if (__elems_before < difference_type(__length / 2)) | |
| { | |
| iterator __new_start = _M_reserve_elements_at_front(__n); | |
| iterator __old_start = this->_M_impl._M_start; | |
| __pos = this->_M_impl._M_start + __elems_before; | |
| __try | |
| { | |
| if (__elems_before >= difference_type(__n)) | |
| { | |
| iterator __start_n = (this->_M_impl._M_start | |
| + difference_type(__n)); | |
| std::__uninitialized_move_a(this->_M_impl._M_start, | |
| __start_n, __new_start, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| _GLIBCXX_MOVE3(__start_n, __pos, __old_start); | |
| std::fill(__pos - difference_type(__n), __pos, __x_copy); | |
| } | |
| else | |
| { | |
| std::__uninitialized_move_fill(this->_M_impl._M_start, | |
| __pos, __new_start, | |
| this->_M_impl._M_start, | |
| __x_copy, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| std::fill(__old_start, __pos, __x_copy); | |
| } | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(__new_start._M_node, | |
| this->_M_impl._M_start._M_node); | |
| __throw_exception_again; | |
| } | |
| } | |
| else | |
| { | |
| iterator __new_finish = _M_reserve_elements_at_back(__n); | |
| iterator __old_finish = this->_M_impl._M_finish; | |
| const difference_type __elems_after = | |
| difference_type(__length) - __elems_before; | |
| __pos = this->_M_impl._M_finish - __elems_after; | |
| __try | |
| { | |
| if (__elems_after > difference_type(__n)) | |
| { | |
| iterator __finish_n = (this->_M_impl._M_finish | |
| - difference_type(__n)); | |
| std::__uninitialized_move_a(__finish_n, | |
| this->_M_impl._M_finish, | |
| this->_M_impl._M_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); | |
| std::fill(__pos, __pos + difference_type(__n), __x_copy); | |
| } | |
| else | |
| { | |
| std::__uninitialized_fill_move(this->_M_impl._M_finish, | |
| __pos + difference_type(__n), | |
| __x_copy, __pos, | |
| this->_M_impl._M_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| std::fill(__pos, __old_finish, __x_copy); | |
| } | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, | |
| __new_finish._M_node + 1); | |
| __throw_exception_again; | |
| } | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| template <typename _ForwardIterator> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_insert_aux(iterator __pos, | |
| _ForwardIterator __first, _ForwardIterator __last, | |
| size_type __n) | |
| { | |
| const difference_type __elemsbefore = __pos - this->_M_impl._M_start; | |
| const size_type __length = size(); | |
| if (static_cast<size_type>(__elemsbefore) < __length / 2) | |
| { | |
| iterator __new_start = _M_reserve_elements_at_front(__n); | |
| iterator __old_start = this->_M_impl._M_start; | |
| __pos = this->_M_impl._M_start + __elemsbefore; | |
| __try | |
| { | |
| if (__elemsbefore >= difference_type(__n)) | |
| { | |
| iterator __start_n = (this->_M_impl._M_start | |
| + difference_type(__n)); | |
| std::__uninitialized_move_a(this->_M_impl._M_start, | |
| __start_n, __new_start, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| _GLIBCXX_MOVE3(__start_n, __pos, __old_start); | |
| std::copy(__first, __last, __pos - difference_type(__n)); | |
| } | |
| else | |
| { | |
| _ForwardIterator __mid = __first; | |
| std::advance(__mid, difference_type(__n) - __elemsbefore); | |
| std::__uninitialized_move_copy(this->_M_impl._M_start, | |
| __pos, __first, __mid, | |
| __new_start, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_start = __new_start; | |
| std::copy(__mid, __last, __old_start); | |
| } | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(__new_start._M_node, | |
| this->_M_impl._M_start._M_node); | |
| __throw_exception_again; | |
| } | |
| } | |
| else | |
| { | |
| iterator __new_finish = _M_reserve_elements_at_back(__n); | |
| iterator __old_finish = this->_M_impl._M_finish; | |
| const difference_type __elemsafter = | |
| difference_type(__length) - __elemsbefore; | |
| __pos = this->_M_impl._M_finish - __elemsafter; | |
| __try | |
| { | |
| if (__elemsafter > difference_type(__n)) | |
| { | |
| iterator __finish_n = (this->_M_impl._M_finish | |
| - difference_type(__n)); | |
| std::__uninitialized_move_a(__finish_n, | |
| this->_M_impl._M_finish, | |
| this->_M_impl._M_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); | |
| std::copy(__first, __last, __pos); | |
| } | |
| else | |
| { | |
| _ForwardIterator __mid = __first; | |
| std::advance(__mid, __elemsafter); | |
| std::__uninitialized_copy_move(__mid, __last, __pos, | |
| this->_M_impl._M_finish, | |
| this->_M_impl._M_finish, | |
| _M_get_Tp_allocator()); | |
| this->_M_impl._M_finish = __new_finish; | |
| std::copy(__first, __mid, __pos); | |
| } | |
| } | |
| __catch(...) | |
| { | |
| _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, | |
| __new_finish._M_node + 1); | |
| __throw_exception_again; | |
| } | |
| } | |
| } | |
| #if __glibcxx_containers_ranges // C++ >= 23 | |
| template<ranges::forward_range _Rg> | |
| _GLIBCXX26_CONSTEXPR auto | |
| __advance_dist(_Rg& __rg) | |
| { | |
| struct _Res | |
| { | |
| ranges::iterator_t<_Rg> __last; | |
| ranges::range_difference_t<_Rg> __size; | |
| }; | |
| if constexpr (ranges::common_range<_Rg>) | |
| return _Res{ranges::end(__rg), ranges::distance(__rg)}; | |
| else if constexpr (ranges::sized_range<_Rg>) | |
| { | |
| auto const __n = ranges::distance(__rg); | |
| auto __it = ranges::begin(__rg); | |
| if constexpr (ranges::random_access_range<_Rg>) | |
| __it += __n; | |
| else | |
| ranges::advance(__it, ranges::end(__rg)); | |
| return _Res{__it, __n}; | |
| } | |
| else | |
| { | |
| auto __it = ranges::begin(__rg); | |
| auto const __last = ranges::end(__rg); | |
| ranges::range_difference_t<_Rg> __n(0); | |
| for (; __it != __last; ++__it) | |
| ++__n; | |
| return _Res{__it, __n}; | |
| } | |
| } | |
| template<typename _Tp, typename _Alloc> | |
| template<__detail::__container_compatible_range<_Tp> _Rg> | |
| _GLIBCXX26_CONSTEXPR auto | |
| deque<_Tp, _Alloc>:: | |
| insert_range(const_iterator __pos, _Rg&& __rg) | |
| -> iterator | |
| { | |
| if (__pos == cend()) | |
| { | |
| const auto __ins_idx = size(); | |
| append_range(std::forward<_Rg>(__rg)); | |
| return begin() + __ins_idx; | |
| } | |
| if (__pos == cbegin()) | |
| { | |
| prepend_range(std::forward<_Rg>(__rg)); | |
| return begin(); | |
| } | |
| const auto __ins_idx = __pos - cbegin(); | |
| if constexpr (ranges::forward_range<_Rg>) | |
| { | |
| auto [__last, __n] = __advance_dist(__rg); | |
| if (__n != 0) [[likely]] | |
| _M_insert_aux(__pos._M_const_cast(), | |
| ranges::begin(__rg), __last, | |
| __n); | |
| } | |
| else | |
| { | |
| auto __first = ranges::begin(__rg); | |
| const auto __last = ranges::end(__rg); | |
| for (auto __it = __pos._M_const_cast(); __first != __last; | |
| (void)++__first, ++__it) | |
| __it = _M_emplace_aux(__it, *__first); | |
| } | |
| return begin() + __ins_idx; | |
| } | |
| template<typename _Tp, typename _Alloc> | |
| template<__detail::__container_compatible_range<_Tp> _Rg> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| prepend_range(_Rg&& __rg) | |
| { | |
| if (empty()) | |
| append_range(std::forward<_Rg>(__rg)); | |
| else if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) | |
| { | |
| const size_type __n(ranges::distance(__rg)); | |
| if (__n != 0) [[likely]] | |
| _M_range_prepend(ranges::begin(__rg), ranges::end(__rg), __n); | |
| } | |
| else | |
| { | |
| struct _Guard_elts_front | |
| { | |
| deque& __self; | |
| size_type __n = 0; | |
| ~_Guard_elts_front() | |
| { | |
| if (__n > 0) | |
| __self._M_erase_at_begin(__self.begin() + __n); | |
| } | |
| }; | |
| _Guard_elts_front __guard{*this}; | |
| auto __first = ranges::begin(__rg); | |
| const auto __last = ranges::end(__rg); | |
| for (; __first != __last; (void)++__first, ++__guard.__n) | |
| emplace_front(*__first); | |
| for (auto __fins = begin(), __lins = begin() + __guard.__n; | |
| __fins != __lins && __fins != --__lins; ++__fins) | |
| std::iter_swap(__fins, __lins); | |
| __guard.__n = 0; | |
| } | |
| } | |
| template<typename _Tp, typename _Alloc> | |
| template<__detail::__container_compatible_range<_Tp> _Rg> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| append_range(_Rg&& __rg) | |
| { | |
| if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) | |
| { | |
| const size_type __n(ranges::distance(__rg)); | |
| if (__n != 0) [[likely]] | |
| _M_range_append(ranges::begin(__rg), ranges::end(__rg), __n); | |
| } | |
| else | |
| { | |
| struct _Guard_elts_back | |
| { | |
| deque& __self; | |
| size_type __n = __self.size(); | |
| _GLIBCXX26_CONSTEXPR | |
| ~_Guard_elts_back() | |
| { | |
| if (__n < __self.size()) | |
| __self._M_erase_at_end(__self.begin() + __n); | |
| } | |
| }; | |
| _Guard_elts_back __guard{*this}; | |
| auto __first = ranges::begin(__rg); | |
| const auto __last = ranges::end(__rg); | |
| for (; __first != __last; (void)++__first) | |
| emplace_back(*__first); | |
| __guard.__n = size(); | |
| } | |
| } | |
| #endif // containers_ranges | |
| template<typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_destroy_data_aux(iterator __first, iterator __last) | |
| { | |
| for (_Map_pointer __node = __first._M_node + 1; | |
| __node < __last._M_node; ++__node) | |
| std::_Destroy(*__node, *__node + _S_buffer_size(), | |
| _M_get_Tp_allocator()); | |
| if (__first._M_node != __last._M_node) | |
| { | |
| std::_Destroy(__first._M_cur, __first._M_last, | |
| _M_get_Tp_allocator()); | |
| std::_Destroy(__last._M_first, __last._M_cur, | |
| _M_get_Tp_allocator()); | |
| } | |
| else | |
| std::_Destroy(__first._M_cur, __last._M_cur, | |
| _M_get_Tp_allocator()); | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_new_elements_at_front(size_type __new_elems) | |
| { | |
| if (this->max_size() - this->size() < __new_elems) | |
| __throw_length_error(__N("deque::_M_new_elements_at_front")); | |
| const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) | |
| / _S_buffer_size()); | |
| _M_reserve_map_at_front(__new_nodes); | |
| size_type __i; | |
| __try | |
| { | |
| for (__i = 1; __i <= __new_nodes; ++__i) | |
| *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); | |
| } | |
| __catch(...) | |
| { | |
| for (size_type __j = 1; __j < __i; ++__j) | |
| _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_new_elements_at_back(size_type __new_elems) | |
| { | |
| if (this->max_size() - this->size() < __new_elems) | |
| __throw_length_error(__N("deque::_M_new_elements_at_back")); | |
| const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) | |
| / _S_buffer_size()); | |
| _M_reserve_map_at_back(__new_nodes); | |
| size_type __i; | |
| __try | |
| { | |
| for (__i = 1; __i <= __new_nodes; ++__i) | |
| *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); | |
| } | |
| __catch(...) | |
| { | |
| for (size_type __j = 1; __j < __i; ++__j) | |
| _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); | |
| __throw_exception_again; | |
| } | |
| } | |
| template <typename _Tp, typename _Alloc> | |
| _GLIBCXX26_CONSTEXPR void | |
| deque<_Tp, _Alloc>:: | |
| _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) | |
| { | |
| const size_type __old_num_nodes | |
| = this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1; | |
| const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; | |
| _Map_pointer __new_nstart; | |
| if (this->_M_impl._M_map_size > 2 * __new_num_nodes) | |
| { | |
| __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size | |
| - __new_num_nodes) / 2 | |
| + (__add_at_front ? __nodes_to_add : 0); | |
| if (__new_nstart < this->_M_impl._M_start._M_node) | |
| std::copy(this->_M_impl._M_start._M_node, | |
| this->_M_impl._M_finish._M_node + 1, | |
| __new_nstart); | |
| else | |
| std::copy_backward(this->_M_impl._M_start._M_node, | |
| this->_M_impl._M_finish._M_node + 1, | |
| __new_nstart + __old_num_nodes); | |
| } | |
| else | |
| { | |
| size_type __new_map_size = this->_M_impl._M_map_size | |
| + std::max(this->_M_impl._M_map_size, | |
| __nodes_to_add) + 2; | |
| const size_t __bufsz = __deque_buf_size(sizeof(_Tp)); | |
| if (__new_map_size > ((max_size() + __bufsz - 1) / __bufsz) * 2) | |
| __builtin_unreachable(); | |
| _Map_pointer __new_map = this->_M_allocate_map(__new_map_size); | |
| __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 | |
| + (__add_at_front ? __nodes_to_add : 0); | |
| std::copy(this->_M_impl._M_start._M_node, | |
| this->_M_impl._M_finish._M_node + 1, | |
| __new_nstart); | |
| _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); | |
| this->_M_impl._M_map = __new_map; | |
| this->_M_impl._M_map_size = __new_map_size; | |
| } | |
| this->_M_impl._M_start._M_set_node(__new_nstart); | |
| this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); | |
| } | |
| _GLIBCXX_END_NAMESPACE_CONTAINER | |
| // Overload for deque::iterators, exploiting the "segmented-iterator | |
| // optimization". | |
| template<typename _Tp, typename _VTp> | |
| _GLIBCXX26_CONSTEXPR void | |
| __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __first, | |
| const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __last, | |
| const _VTp& __value) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; | |
| if (__first._M_node != __last._M_node) | |
| { | |
| std::__fill_a1(__first._M_cur, __first._M_last, __value); | |
| for (typename _Iter::_Map_pointer __node = __first._M_node + 1; | |
| __node < __last._M_node; ++__node) | |
| std::__fill_a1(*__node, *__node + _Iter::_S_buffer_size(), __value); | |
| std::__fill_a1(__last._M_first, __last._M_cur, __value); | |
| } | |
| else | |
| std::__fill_a1(__first._M_cur, __last._M_cur, __value); | |
| } | |
| template<bool _IsMove, | |
| typename _Tp, typename _Ref, typename _Ptr, typename _OI> | |
| _GLIBCXX26_CONSTEXPR _OI | |
| __copy_move_dit(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, | |
| _OI __result) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; | |
| if (__first._M_node != __last._M_node) | |
| { | |
| __result | |
| = std::__copy_move_a1<_IsMove>(__first._M_cur, __first._M_last, | |
| __result); | |
| for (typename _Iter::_Map_pointer __node = __first._M_node + 1; | |
| __node != __last._M_node; ++__node) | |
| __result | |
| = std::__copy_move_a1<_IsMove>(*__node, | |
| *__node + _Iter::_S_buffer_size(), | |
| __result); | |
| return std::__copy_move_a1<_IsMove>(__last._M_first, __last._M_cur, | |
| __result); | |
| } | |
| return std::__copy_move_a1<_IsMove>(__first._M_cur, __last._M_cur, | |
| __result); | |
| } | |
| template<bool _IsMove, | |
| typename _Tp, typename _Ref, typename _Ptr, typename _OI> | |
| _GLIBCXX26_CONSTEXPR _OI | |
| __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, | |
| _OI __result) | |
| { return __copy_move_dit<_IsMove>(__first, __last, __result); } | |
| template<bool _IsMove, | |
| typename _ITp, typename _IRef, typename _IPtr, typename _OTp> | |
| _GLIBCXX26_CONSTEXPR | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> | |
| __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) | |
| { return __copy_move_dit<_IsMove>(__first, __last, __result); } | |
| template<bool _IsMove, typename _II, typename _Tp> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_any_random_access_iter<_II>::__value, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type | |
| __copy_move_a1(_II __first, _II __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; | |
| typedef typename _Iter::difference_type difference_type; | |
| difference_type __len = __last - __first; | |
| while (__len > 0) | |
| { | |
| const difference_type __clen | |
| = std::min(__len, __result._M_last - __result._M_cur); | |
| std::__copy_move_a1<_IsMove>(__first, __first + __clen, | |
| __result._M_cur); | |
| __first += __clen; | |
| __result += __clen; | |
| __len -= __clen; | |
| } | |
| return __result; | |
| } | |
| template<bool _IsMove, typename _CharT> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_char<_CharT>::__value, | |
| _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type | |
| __copy_move_a2( | |
| istreambuf_iterator<_CharT, char_traits<_CharT> > __first, | |
| istreambuf_iterator<_CharT, char_traits<_CharT> > __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result) | |
| { | |
| if (__first == __last) | |
| return __result; | |
| for (;;) | |
| { | |
| const std::ptrdiff_t __len = __result._M_last - __result._M_cur; | |
| const std::ptrdiff_t __nb | |
| = std::__copy_n_a(__first, __len, __result._M_cur, false) | |
| - __result._M_cur; | |
| __result += __nb; | |
| if (__nb != __len) | |
| break; | |
| } | |
| return __result; | |
| } | |
| template<typename _CharT, typename _Size> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_char<_CharT>::__value, | |
| _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> >::__type | |
| __copy_n_a( | |
| istreambuf_iterator<_CharT, char_traits<_CharT> > __it, _Size __size, | |
| _GLIBCXX_STD_C::_Deque_iterator<_CharT, _CharT&, _CharT*> __result, | |
| bool __strict) | |
| { | |
| if (__size == 0) | |
| return __result; | |
| do | |
| { | |
| const _Size __len | |
| = std::min<_Size>(__result._M_last - __result._M_cur, __size); | |
| std::__copy_n_a(__it, __len, __result._M_cur, __strict); | |
| __result += __len; | |
| __size -= __len; | |
| } | |
| while (__size != 0); | |
| return __result; | |
| } | |
| template<bool _IsMove, | |
| typename _Tp, typename _Ref, typename _Ptr, typename _OI> | |
| _GLIBCXX26_CONSTEXPR _OI | |
| __copy_move_backward_dit( | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, | |
| _OI __result) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; | |
| if (__first._M_node != __last._M_node) | |
| { | |
| __result = std::__copy_move_backward_a1<_IsMove>( | |
| __last._M_first, __last._M_cur, __result); | |
| for (typename _Iter::_Map_pointer __node = __last._M_node - 1; | |
| __node != __first._M_node; --__node) | |
| __result = std::__copy_move_backward_a1<_IsMove>( | |
| *__node, *__node + _Iter::_S_buffer_size(), __result); | |
| return std::__copy_move_backward_a1<_IsMove>( | |
| __first._M_cur, __first._M_last, __result); | |
| } | |
| return std::__copy_move_backward_a1<_IsMove>( | |
| __first._M_cur, __last._M_cur, __result); | |
| } | |
| template<bool _IsMove, | |
| typename _Tp, typename _Ref, typename _Ptr, typename _OI> | |
| _GLIBCXX26_CONSTEXPR _OI | |
| __copy_move_backward_a1( | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, | |
| _OI __result) | |
| { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } | |
| template<bool _IsMove, | |
| typename _ITp, typename _IRef, typename _IPtr, typename _OTp> | |
| _GLIBCXX26_CONSTEXPR | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> | |
| __copy_move_backward_a1( | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) | |
| { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } | |
| template<bool _IsMove, typename _II, typename _Tp> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_any_random_access_iter<_II>::__value, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type | |
| __copy_move_backward_a1(_II __first, _II __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; | |
| typedef typename _Iter::difference_type difference_type; | |
| difference_type __len = __last - __first; | |
| while (__len > 0) | |
| { | |
| difference_type __rlen = __result._M_cur - __result._M_first; | |
| _Tp* __rend = __result._M_cur; | |
| if (!__rlen) | |
| { | |
| __rlen = _Iter::_S_buffer_size(); | |
| __rend = *(__result._M_node - 1) + __rlen; | |
| } | |
| const difference_type __clen = std::min(__len, __rlen); | |
| std::__copy_move_backward_a1<_IsMove>(__last - __clen, __last, __rend); | |
| __last -= __clen; | |
| __result -= __clen; | |
| __len -= __clen; | |
| } | |
| return __result; | |
| } | |
| template<typename _Tp, typename _Ref, typename _Ptr, typename _II> | |
| _GLIBCXX26_CONSTEXPR bool | |
| __equal_dit( | |
| const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __first1, | |
| const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __last1, | |
| _II __first2) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; | |
| if (__first1._M_node != __last1._M_node) | |
| { | |
| if (!std::__equal_aux1(__first1._M_cur, __first1._M_last, __first2)) | |
| return false; | |
| __first2 += __first1._M_last - __first1._M_cur; | |
| for (typename _Iter::_Map_pointer __node = __first1._M_node + 1; | |
| __node != __last1._M_node; | |
| __first2 += _Iter::_S_buffer_size(), ++__node) | |
| if (!std::__equal_aux1(*__node, *__node + _Iter::_S_buffer_size(), | |
| __first2)) | |
| return false; | |
| return std::__equal_aux1(__last1._M_first, __last1._M_cur, __first2); | |
| } | |
| return std::__equal_aux1(__first1._M_cur, __last1._M_cur, __first2); | |
| } | |
| template<typename _Tp, typename _Ref, typename _Ptr, typename _II> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_any_random_access_iter<_II>::__value, bool>::__type | |
| __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last1, | |
| _II __first2) | |
| { return std::__equal_dit(__first1, __last1, __first2); } | |
| template<typename _Tp1, typename _Ref1, typename _Ptr1, | |
| typename _Tp2, typename _Ref2, typename _Ptr2> | |
| _GLIBCXX26_CONSTEXPR bool | |
| __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2) | |
| { return std::__equal_dit(__first1, __last1, __first2); } | |
| template<typename _II, typename _Tp, typename _Ref, typename _Ptr> | |
| _GLIBCXX26_CONSTEXPR | |
| typename __gnu_cxx::__enable_if< | |
| __is_any_random_access_iter<_II>::__value, bool>::__type | |
| __equal_aux1(_II __first1, _II __last1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first2) | |
| { | |
| typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; | |
| typedef typename _Iter::difference_type difference_type; | |
| difference_type __len = __last1 - __first1; | |
| while (__len > 0) | |
| { | |
| const difference_type __clen | |
| = std::min(__len, __first2._M_last - __first2._M_cur); | |
| if (!std::__equal_aux1(__first1, __first1 + __clen, __first2._M_cur)) | |
| return false; | |
| __first1 += __clen; | |
| __len -= __clen; | |
| __first2 += __clen; | |
| } | |
| return true; | |
| } | |
| template<typename _Tp1, typename _Ref, typename _Ptr, typename _Tp2> | |
| _GLIBCXX26_CONSTEXPR int | |
| __lex_cmp_dit( | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref, _Ptr> __first1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref, _Ptr> __last1, | |
| const _Tp2* __first2, const _Tp2* __last2) | |
| { | |
| #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer) | |
| const bool __simple = | |
| (__is_memcmp_ordered_with<_Tp1, _Tp2>::__value | |
| && __is_pointer(_Ptr) | |
| #if __cplusplus > 201703L && __cpp_lib_concepts | |
| // For C++20 iterator_traits<volatile T*>::value_type is non-volatile | |
| // so __is_byte<T> could be true, but we can't use memcmp with | |
| // volatile data. | |
| && !is_volatile_v<_Tp1> && !is_volatile_v<_Tp2> | |
| #endif | |
| ); | |
| typedef std::__lexicographical_compare<__simple> _Lc; | |
| #else | |
| typedef std::__lexicographical_compare<false> _Lc; | |
| #endif | |
| while (__first1._M_node != __last1._M_node) | |
| { | |
| const ptrdiff_t __len1 = __first1._M_last - __first1._M_cur; | |
| const ptrdiff_t __len2 = __last2 - __first2; | |
| const ptrdiff_t __len = std::min(__len1, __len2); | |
| // if __len1 > __len2 this will return a positive value: | |
| if (int __ret = _Lc::__3way(__first1._M_cur, __first1._M_last, | |
| __first2, __first2 + __len)) | |
| return __ret; | |
| __first1 += __len; | |
| __first2 += __len; | |
| } | |
| return _Lc::__3way(__first1._M_cur, __last1._M_cur, | |
| __first2, __last2); | |
| } | |
| template<typename _Tp1, typename _Ref1, typename _Ptr1, | |
| typename _Tp2> | |
| inline _GLIBCXX26_CONSTEXPR bool | |
| __lexicographical_compare_aux1( | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, | |
| _Tp2* __first2, _Tp2* __last2) | |
| { return std::__lex_cmp_dit(__first1, __last1, __first2, __last2) < 0; } | |
| template<typename _Tp1, | |
| typename _Tp2, typename _Ref2, typename _Ptr2> | |
| inline _GLIBCXX26_CONSTEXPR bool | |
| __lexicographical_compare_aux1(_Tp1* __first1, _Tp1* __last1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __last2) | |
| { return std::__lex_cmp_dit(__first2, __last2, __first1, __last1) > 0; } | |
| template<typename _Tp1, typename _Ref1, typename _Ptr1, | |
| typename _Tp2, typename _Ref2, typename _Ptr2> | |
| inline _GLIBCXX26_CONSTEXPR bool | |
| __lexicographical_compare_aux1( | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2, | |
| _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __last2) | |
| { | |
| #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_pointer) | |
| const bool __simple = | |
| (__is_memcmp_ordered_with<_Tp1, _Tp2>::__value | |
| && __is_pointer(_Ptr1) && __is_pointer(_Ptr2) | |
| #if __cplusplus > 201703L && __cpp_lib_concepts | |
| // For C++20 iterator_traits<volatile T*>::value_type is non-volatile | |
| // so __is_byte<T> could be true, but we can't use memcmp with | |
| // volatile data. | |
| && !is_volatile_v<_Tp1> && !is_volatile_v<_Tp2> | |
| #endif | |
| ); | |
| typedef std::__lexicographical_compare<__simple> _Lc; | |
| #else | |
| typedef std::__lexicographical_compare<false> _Lc; | |
| #endif | |
| while (__first1 != __last1) | |
| { | |
| const ptrdiff_t __len2 = __first2._M_node == __last2._M_node | |
| ? __last2._M_cur - __first2._M_cur | |
| : __first2._M_last - __first2._M_cur; | |
| if (__len2 == 0) | |
| return false; | |
| const ptrdiff_t __len1 = __first1._M_node == __last1._M_node | |
| ? __last1._M_cur - __first1._M_cur | |
| : __first1._M_last - __first1._M_cur; | |
| const ptrdiff_t __len = std::min(__len1, __len2); | |
| if (int __ret = _Lc::__3way(__first1._M_cur, __first1._M_cur + __len, | |
| __first2._M_cur, __first2._M_cur + __len)) | |
| return __ret < 0; | |
| __first1 += __len; | |
| __first2 += __len; | |
| } | |
| return __last2 != __first2; | |
| } | |
| #if __cplusplus >= 201103L | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr | |
| template<typename _ITp, typename _IRef, typename _IPtr, typename _OTp, | |
| typename _Tp> | |
| _GLIBCXX26_CONSTEXPR | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> | |
| __uninitialized_copy_a( | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result, | |
| allocator<_Tp>&) | |
| { | |
| // In order to unwind all initialized elements, we just use the default | |
| // implementation if construction can throw. | |
| if constexpr (!__is_nothrow_constructible(_OTp, _IRef)) | |
| return std::__do_uninit_copy(__first, __last, __result); | |
| else | |
| while (__first != __last) | |
| { | |
| auto __from = __first._M_cur; | |
| ptrdiff_t __n; | |
| if (__first._M_node == __last._M_node) | |
| __n = __last._M_cur - __from; | |
| else | |
| __n = __first._M_last - __from; | |
| __n = std::min<ptrdiff_t>(__n, __result._M_last - __result._M_cur); | |
| std::uninitialized_copy(__from, __from + __n, __result._M_cur); | |
| __first += __n; | |
| __result += __n; | |
| } | |
| return __result; | |
| } | |
| template<typename _Iter, typename _OTp, typename _Tp> | |
| _GLIBCXX26_CONSTEXPR | |
| __enable_if_t<__is_random_access_iter<_Iter>::value, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>> | |
| __uninitialized_copy_a(_Iter __first, _Iter __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result, | |
| allocator<_Tp>&) | |
| { | |
| // In order to unwind all initialized elements, we just use the default | |
| // implementation if construction can throw. | |
| if constexpr (!__is_nothrow_constructible(_OTp, decltype(*__first))) | |
| return std::__do_uninit_copy(__first, __last, __result); | |
| else | |
| while (__first != __last) | |
| { | |
| auto __n = std::min<ptrdiff_t>(__last - __first, | |
| __result._M_last - __result._M_cur); | |
| std::uninitialized_copy(__first, __first + __n, __result._M_cur); | |
| __first += __n; | |
| __result += __n; | |
| } | |
| return __result; | |
| } | |
| template<typename _ITp, typename _IRef, typename _IPtr, typename _OTp, | |
| typename _Tp> | |
| _GLIBCXX26_CONSTEXPR | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> | |
| __uninitialized_move_a( | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, | |
| _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, | |
| _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result, | |
| allocator<_Tp>&) | |
| { | |
| // In order to unwind all initialized elements, we just use the default | |
| // implementation if construction can throw. | |
| if constexpr (!__is_nothrow_constructible(_OTp, | |
| decltype(std::move(*__first)))) | |
| return std::uninitialized_copy(std::make_move_iterator(__first), | |
| std::make_move_iterator(__last), | |
| __result); | |
| else | |
| while (__first != __last) | |
| { | |
| auto __from = __first._M_cur; | |
| ptrdiff_t __n; | |
| if (__first._M_node == __last._M_node) | |
| __n = __last._M_cur - __from; | |
| else | |
| __n = __first._M_last - __from; | |
| __n = std::min<ptrdiff_t>(__n, __result._M_last - __result._M_cur); | |
| std::uninitialized_copy(std::make_move_iterator(__from), | |
| std::make_move_iterator(__from + __n), | |
| __result._M_cur); | |
| __first += __n; | |
| __result += __n; | |
| } | |
| return __result; | |
| } | |
| #pragma GCC diagnostic pop | |
| #endif // C++11 | |
| _GLIBCXX_END_NAMESPACE_VERSION | |
| } // namespace std | |
| #endif |