From 429024ca4e1b9ce73b602b557ddf2da95ec27878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Tue, 16 Apr 2024 11:36:04 +0200 Subject: [PATCH] Add experimental (macro protected) support for lighter iterators --- include/boost/container/deque.hpp | 646 ++++++++++++++++++++++++++---- 1 file changed, 572 insertions(+), 74 deletions(-) diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 157c900..e599581 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -106,6 +106,10 @@ namespace dtl { // [map, map + map_size). // A pointer in the range [map, map + map_size) points to an allocated node // if and only if the pointer is in the range [start.node, finish.node]. + +#define BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL 0 + +#if BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 0 template class deque_iterator { @@ -241,15 +245,15 @@ class deque_iterator if (!n) return *this; BOOST_ASSERT(!!m_cur); - difference_type offset = n + (this->m_cur - this->m_first); + const difference_type offset = n + (this->m_cur - this->m_first); const difference_type block_size = m_last - m_first; BOOST_ASSERT(block_size); if (offset >= 0 && offset < block_size) this->m_cur += difference_type(n); else { - difference_type node_offset = - offset > 0 ? (offset / block_size) - : (-difference_type((-offset - 1) / block_size) - 1); + const difference_type node_offset = + offset > 0 ? (offset / block_size) + : (-difference_type((-offset - 1) / block_size) - 1); this->priv_set_node(this->m_node + node_offset, size_type(block_size)); this->m_cur = this->m_first + (offset - node_offset * block_size); @@ -313,6 +317,447 @@ class deque_iterator } }; +#elif BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 1 + +template +class deque_iterator +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename boost::intrusive::pointer_traits::element_type value_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::intrusive::pointer_traits::size_type size_type; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW + { return deque_block_size::value; } + + BOOST_CONSTEXPR inline static difference_type get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW + { return difference_type((get_block_size())); } + + class nat; + typedef typename dtl::if_c< IsConst + , deque_iterator + , nat>::type nonconst_iterator; + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type index_pointer; + + Pointer m_cur; + Pointer m_first; + index_pointer m_node; + + public: + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_cur() const { return m_cur; } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_first() const { return m_first; } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_last() const { return m_first + get_block_ssize(); } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline index_pointer get_node() const { return m_node; } + + inline deque_iterator(val_alloc_ptr x, index_pointer y, difference_type ) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x), m_first(*y), m_node(y) + {} + + inline deque_iterator(val_alloc_ptr x, index_pointer y, size_type ) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x), m_first(*y), m_node(y) + {} + + inline deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(), m_first(), m_node() //Value initialization to achieve "null iterators" (N3644) + {} + + inline deque_iterator(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x.get_cur()), m_first(x.get_first()), m_node(x.get_node()) + {} + + inline deque_iterator(const nonconst_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x.get_cur()), m_first(x.get_first()), m_node(x.get_node()) + {} + + inline deque_iterator(Pointer cur, Pointer first, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(cur), m_first(first), m_node(node) + {} + + inline deque_iterator& operator=(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + { m_cur = x.get_cur(); m_first = x.get_first(); m_node = x.get_node(); return *this; } + + inline nonconst_iterator unconst() const BOOST_NOEXCEPT_OR_NOTHROW + { + return nonconst_iterator(this->get_cur(), this->get_first(), this->get_node()); + } + + inline reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW + { return *this->m_cur; } + + inline pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW + { + if(!this->m_cur && !x.m_cur){ + return 0; + } + const difference_type block_size = get_block_ssize(); + BOOST_ASSERT(block_size); + return block_size * (this->m_node - x.m_node - 1) + + (this->m_cur - this->m_first) + ((x.m_first+block_size) - x.m_cur); + } + + deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!!m_cur); + ++this->m_cur; + const difference_type block_size = get_block_ssize(); + if (this->m_cur == (this->m_first+block_size)) { + + BOOST_ASSERT(block_size); + ++this->m_node; + this->m_first = *this->m_node; + this->m_cur = this->m_first; + } + return *this; + } + + inline deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW + { + deque_iterator tmp(*this); + ++*this; + return tmp; + } + + deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!!m_cur); + if (this->m_cur == this->m_first) { + --this->m_node; + this->m_first = *this->m_node; + this->m_cur = this->m_first + get_block_ssize(); + } + --this->m_cur; + return *this; + } + + inline deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW + { + deque_iterator tmp(*this); + --*this; + return tmp; + } + + deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + if (!n) + return *this; + BOOST_ASSERT(!!m_cur); + const difference_type offset = n + (this->m_cur - this->m_first); + const difference_type block_size = get_block_ssize(); + BOOST_ASSERT(block_size); + if (offset >= 0 && offset < block_size) + this->m_cur += difference_type(n); + else { + const difference_type node_offset = + offset > 0 ? (offset / block_size) + : (-difference_type((-offset - 1) / block_size) - 1); + this->m_node += node_offset; + this->m_first = *this->m_node; + this->m_cur = this->m_first + (offset - node_offset * block_size); + } + return *this; + } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { deque_iterator tmp(*this); return tmp += n; } + + inline + deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW + { return *this += -n; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { deque_iterator tmp(*this); return tmp -= n; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { return *(*this + n); } + + //Comparisons + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return l.m_cur == r.m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return l.m_cur != r.m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return r < l; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return !(r < l); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return !(l < r); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW + { return x += n; } + + inline void priv_set_node(index_pointer new_node, size_type ) BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_set_node(new_node, difference_type()); } + + inline void priv_set_node(index_pointer new_node, difference_type) BOOST_NOEXCEPT_OR_NOTHROW + { + this->m_node = new_node; + this->m_first = *new_node; + } +}; + +#elif BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 2 + +template +class deque_iterator +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename boost::intrusive::pointer_traits::element_type value_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::intrusive::pointer_traits::size_type size_type; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::type + , Pointer + >::type pointer; + typedef typename if_c + < IsConst + , const value_type& + , value_type& + >::type reference; + + BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_CONTAINER_STATIC_ASSERT((deque_block_size::value)); + return deque_block_size::value; + } + + BOOST_CONSTEXPR inline static difference_type get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW + { return difference_type((get_block_size())); } + + class nat; + typedef typename dtl::if_c< IsConst + , deque_iterator + , nat>::type nonconst_iterator; + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_pointer::type index_pointer; + + Pointer m_cur; + index_pointer m_node; + + public: + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_cur() const { return m_cur; } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_first() const { return *m_node; } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_last() const { return *m_node + get_block_ssize(); } + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline index_pointer get_node() const { return m_node; } + + inline deque_iterator(val_alloc_ptr x, index_pointer y, difference_type ) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x), m_node(y) + {} + + inline deque_iterator(val_alloc_ptr x, index_pointer y, size_type ) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x), m_node(y) + {} + + inline deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(), m_node() //Value initialization to achieve "null iterators" (N3644) + {} + + inline deque_iterator(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x.get_cur()), m_node(x.get_node()) + {} + + inline deque_iterator(const nonconst_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x.get_cur()), m_node(x.get_node()) + {} + + inline deque_iterator(Pointer cur, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(cur), m_node(node) + {} + + inline deque_iterator& operator=(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW + { m_cur = x.get_cur(); m_node = x.get_node(); return *this; } + + inline nonconst_iterator unconst() const BOOST_NOEXCEPT_OR_NOTHROW + { + return nonconst_iterator(this->get_cur(), this->get_node()); + } + + inline reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW + { return *this->m_cur; } + + inline pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW + { + if(!this->m_cur && !x.m_cur){ + return 0; + } + const difference_type block_size = get_block_ssize(); + BOOST_ASSERT(block_size); + return block_size * (this->m_node - x.m_node - 1) + + (this->m_cur - this->get_first()) + (x.get_last() - x.m_cur); + } + + deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!!m_cur); + ++this->m_cur; + if (this->m_cur == (this->get_last())) { + + ++this->m_node; + this->m_cur = *this->m_node; + } + return *this; + } + + inline deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW + { + deque_iterator tmp(*this); + ++*this; + return tmp; + } + + deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!!m_cur); + if (this->m_cur == this->get_first()) { + --this->m_node; + this->m_cur = this->get_last(); + } + --this->m_cur; + return *this; + } + + inline deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW + { + deque_iterator tmp(*this); + --*this; + return tmp; + } + + deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + if (!n) + return *this; + BOOST_ASSERT(!!m_cur); + const difference_type offset = n + (this->m_cur - this->get_first()); + const difference_type block_size = get_block_ssize(); + BOOST_ASSERT(block_size); + if (offset >= 0 && offset < block_size) + this->m_cur += difference_type(n); + else { + const difference_type node_offset = + offset > 0 ? (offset / block_size) + : (-difference_type((-offset - 1) / block_size) - 1); + this->m_node += node_offset; + this->m_cur = this->get_first() + (offset - node_offset * block_size); + } + return *this; + } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { deque_iterator tmp(*this); return tmp += n; } + + inline + deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW + { return *this += -n; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { deque_iterator tmp(*this); return tmp -= n; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!!m_cur); + const difference_type offset = n + (this->m_cur - this->get_first()); + const difference_type block_size = get_block_ssize(); + if (offset >= 0 && offset < block_size) + return this->m_cur[difference_type(n)]; + else { + const difference_type node_offset = offset > 0 + ? (offset / block_size) + : (-difference_type((-offset - 1) / block_size) - 1); + return (this->m_node[node_offset]) [offset - node_offset * block_size]; + } + } + + //Comparisons + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return l.m_cur == r.m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return l.m_cur != r.m_cur; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return r < l; } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return !(r < l); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW + { return !(l < r); } + + BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline + friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW + { return x += n; } + + inline void priv_set_node(index_pointer new_node, size_type ) BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_set_node(new_node, difference_type()); } + + inline void priv_set_node(index_pointer new_node, difference_type) BOOST_NOEXCEPT_OR_NOTHROW + { + this->m_node = new_node; + } +}; + +#else + +#error "Invalid BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL" + +#endif } //namespace dtl { template @@ -360,15 +805,20 @@ class deque_base typedef typename get_deque_opt::type options_type; protected: + #if BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 0 typedef dtl::deque_iterator iterator; - typedef dtl::deque_iterator const_iterator; + typedef dtl::deque_iterator const_iterator; + #else + typedef dtl::deque_iterator iterator; + typedef dtl::deque_iterator const_iterator; + #endif + + BOOST_CONSTEXPR inline static val_alloc_diff get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW + { return val_alloc_diff((get_block_size())); } BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW { return deque_block_size::value; } - BOOST_CONSTEXPR inline static val_alloc_diff get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW - { return val_alloc_diff((get_block_size)()); } - typedef deque_value_traits traits_t; typedef ptr_alloc_t map_allocator_type; @@ -446,8 +896,8 @@ class deque_base this->members_.m_start.priv_set_node(nstart, get_block_size()); this->members_.m_finish.priv_set_node(nfinish - 1, get_block_size()); - this->members_.m_start.m_cur = this->members_.m_start.m_first; - this->members_.m_finish.m_cur = this->members_.m_finish.m_first + difference_type(num_elements % get_block_size()); + this->members_.m_start.m_cur = this->members_.m_start.get_first(); + this->members_.m_finish.m_cur = this->members_.m_finish.get_first() + difference_type(num_elements % get_block_size()); // } } @@ -1741,7 +2191,7 @@ class deque : protected deque_base::type, void pop_front() BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { + if (this->members_.m_start.m_cur != this->members_.m_start.get_last() - 1) { allocator_traits_type::destroy ( this->alloc() , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) @@ -1760,7 +2210,7 @@ class deque : protected deque_base::type, void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { + if (this->members_.m_finish.m_cur != this->members_.m_finish.get_first()) { --this->members_.m_finish.m_cur; allocator_traits_type::destroy ( this->alloc() @@ -1865,9 +2315,9 @@ class deque : protected deque_base::type, } if (this->members_.m_start.m_node != this->members_.m_finish.m_node) { - this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last); - this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur); - this->priv_deallocate_node(this->members_.m_finish.m_first); + this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.get_last()); + this->priv_destroy_range(this->members_.m_finish.get_first(), this->members_.m_finish.m_cur); + this->priv_deallocate_node(this->members_.m_finish.get_first()); } else this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur); @@ -2016,7 +2466,7 @@ class deque : protected deque_base::type, inline bool priv_push_back_simple_available() const { return this->members_.m_map && - (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1)); + (this->members_.m_finish.m_cur != (this->members_.m_finish.get_last() - 1)); } inline T *priv_push_back_simple_pos() const @@ -2032,7 +2482,7 @@ class deque : protected deque_base::type, inline bool priv_push_front_simple_available() const { return this->members_.m_map && - (this->members_.m_start.m_cur != this->members_.m_start.m_first); + (this->members_.m_start.m_cur != this->members_.m_start.get_first()); } inline T *priv_push_front_simple_pos() const @@ -2060,84 +2510,117 @@ class deque : protected deque_base::type, } template - iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy) + iterator priv_insert_middle_aux_impl(const_iterator p, const size_type elemsbefore, const size_type length, const size_type n, InsertProxy proxy) { - iterator pos(p.unconst()); - const size_type pos_n = size_type(p - this->cbegin()); - if(!this->members_.m_map){ + if (!this->members_.m_map) { this->priv_initialize_map(0); - pos = this->begin(); + p = this->cbegin(); } - const size_type elemsbefore = static_cast(pos - this->members_.m_start); - const size_type length = this->size(); + iterator pos(p.unconst()); + const size_type pos_n = size_type(p - this->cbegin()); + if (elemsbefore < length / 2) { const iterator new_start = this->priv_reserve_elements_at_front(n); const iterator old_start = this->members_.m_start; - if(!elemsbefore){ - proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); - this->members_.m_start = new_start; - } - else{ - pos = this->members_.m_start + difference_type(elemsbefore); - if (elemsbefore >= n) { - const iterator start_n = this->members_.m_start + difference_type(n); + pos = this->members_.m_start + difference_type(elemsbefore); + if (elemsbefore >= n) { + const iterator start_n = this->members_.m_start + difference_type(n); + BOOST_CONTAINER_TRY { ::boost::container::uninitialized_move_alloc (this->alloc(), this->members_.m_start, start_n, new_start); - this->members_.m_start = new_start; - boost::container::move(start_n, pos, old_start); - proxy.copy_n_and_update(this->alloc(), pos - difference_type(n), n); } - else { - const size_type mid_count = n - elemsbefore; - const iterator mid_start = old_start - difference_type(mid_count); + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + this->members_.m_start = new_start; + boost::container::move(start_n, pos, old_start); + proxy.copy_n_and_update(this->alloc(), pos - difference_type(n), n); + } + else { + const size_type mid_count = n - elemsbefore; + const iterator mid_start = old_start - difference_type(mid_count); + BOOST_CONTAINER_TRY { proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count); this->members_.m_start = mid_start; - ::boost::container::uninitialized_move_alloc - (this->alloc(), old_start, pos, new_start); - this->members_.m_start = new_start; - proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore); + ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start); } + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + this->members_.m_start = new_start; + proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore); } } else { const iterator new_finish = this->priv_reserve_elements_at_back(n); const iterator old_finish = this->members_.m_finish; const size_type elemsafter = length - elemsbefore; - if(!elemsafter){ - proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); - this->members_.m_finish = new_finish; - } - else{ - pos = old_finish - difference_type(elemsafter); - if (elemsafter >= n) { - iterator finish_n = old_finish - difference_type(n); - ::boost::container::uninitialized_move_alloc - (this->alloc(), finish_n, old_finish, old_finish); - this->members_.m_finish = new_finish; - boost::container::move_backward(pos, finish_n, old_finish); - proxy.copy_n_and_update(this->alloc(), pos, n); + + pos = old_finish - difference_type(elemsafter); + if (elemsafter >= n) { + iterator finish_n = old_finish - difference_type(n); + BOOST_CONTAINER_TRY { + ::boost::container::uninitialized_move_alloc(this->alloc(), finish_n, old_finish, old_finish); } - else { - const size_type raw_gap = n - elemsafter; + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + + this->members_.m_finish = new_finish; + boost::container::move_backward(pos, finish_n, old_finish); + proxy.copy_n_and_update(this->alloc(), pos, n); + } + else { + const size_type raw_gap = n - elemsafter; + BOOST_CONTAINER_TRY{ ::boost::container::uninitialized_move_alloc (this->alloc(), pos, old_finish, old_finish + difference_type(raw_gap)); BOOST_CONTAINER_TRY{ proxy.copy_n_and_update(this->alloc(), pos, elemsafter); proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap); } - BOOST_CONTAINER_CATCH(...){ + BOOST_CONTAINER_CATCH(...) { this->priv_destroy_range(old_finish, old_finish + difference_type(elemsafter)); BOOST_CONTAINER_RETHROW } BOOST_CONTAINER_CATCH_END - this->members_.m_finish = new_finish; } + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + this->members_.m_finish = new_finish; } } return this->begin() + difference_type(pos_n); } + template + iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy) + { + iterator pos(p.unconst()); + const size_type elemsbefore = static_cast(pos - this->members_.m_start); + const size_type length = this->size(); + + if (!elemsbefore) { + return this->priv_insert_front_aux_impl(n, proxy); + } + else if (elemsbefore == length) { + return this->priv_insert_back_aux_impl(n, proxy); + } + else { + return this->priv_insert_middle_aux_impl(p, elemsbefore, length, n, proxy); + } + } + template iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy) { @@ -2146,8 +2629,14 @@ class deque : protected deque_base::type, } iterator new_finish = this->priv_reserve_elements_at_back(n); - iterator old_finish = this->members_.m_finish; - proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); + BOOST_CONTAINER_TRY{ + proxy.uninitialized_copy_n_and_update(this->alloc(), this->members_.m_finish, n); + } + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END this->members_.m_finish = new_finish; return iterator(this->members_.m_finish - difference_type(n)); } @@ -2160,7 +2649,15 @@ class deque : protected deque_base::type, } iterator new_start = this->priv_reserve_elements_at_front(n); - proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); + BOOST_CONTAINER_TRY{ + proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); + } + BOOST_CONTAINER_CATCH(...) { + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + BOOST_CONTAINER_RETHROW + } + BOOST_CONTAINER_CATCH_END + this->members_.m_start = new_start; return new_start; } @@ -2181,7 +2678,7 @@ class deque : protected deque_base::type, (this->alloc(), *cur, *cur + get_block_ssize(), value); } boost::container::uninitialized_fill_alloc - (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); + (this->alloc(), this->members_.m_finish.get_first(), this->members_.m_finish.m_cur, value); } BOOST_CONTAINER_CATCH(...){ this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur, get_block_size())); @@ -2220,7 +2717,7 @@ class deque : protected deque_base::type, ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node); first = mid; } - ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first); + ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.get_first()); } BOOST_CONTAINER_CATCH(...){ this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node, get_block_size())); @@ -2229,21 +2726,21 @@ class deque : protected deque_base::type, BOOST_CONTAINER_CATCH_END } - // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. + // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.get_first(). void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW { - this->priv_deallocate_node(this->members_.m_finish.m_first); + this->priv_deallocate_node(this->members_.m_finish.get_first()); this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1, get_block_size()); - this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; + this->members_.m_finish.m_cur = this->members_.m_finish.get_last() - 1; allocator_traits_type::destroy ( this->alloc() , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur) ); } - // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that + // Called only if this->members_.m_start.m_cur == this->members_.m_start.get_last() - 1. Note that // if the deque has at least one element (a precondition for this member - // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque + // function), and if this->members_.m_start.m_cur == this->members_.m_start.get_last(), then the deque // must have at least two nodes. void priv_pop_front_aux() BOOST_NOEXCEPT_OR_NOTHROW { @@ -2251,14 +2748,14 @@ class deque : protected deque_base::type, ( this->alloc() , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) ); - this->priv_deallocate_node(this->members_.m_start.m_first); + this->priv_deallocate_node(this->members_.m_start.get_first()); this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1, get_block_size()); - this->members_.m_start.m_cur = this->members_.m_start.m_first; + this->members_.m_start.m_cur = this->members_.m_start.get_first(); } iterator priv_reserve_elements_at_front(size_type n) { - size_type vacancies = size_type(this->members_.m_start.m_cur - this->members_.m_start.m_first); + size_type vacancies = size_type(this->members_.m_start.m_cur - this->members_.m_start.get_first()); if (n > vacancies){ size_type new_elems = n-vacancies; size_type new_nodes = (new_elems + get_block_size() - 1u) / get_block_size(); @@ -2283,7 +2780,7 @@ class deque : protected deque_base::type, iterator priv_reserve_elements_at_back(size_type n) { - size_type vacancies = size_type(this->members_.m_finish.m_last - this->members_.m_finish.m_cur - 1); + size_type vacancies = size_type(this->members_.m_finish.get_last() - this->members_.m_finish.m_cur - 1); if (n > vacancies){ size_type new_elems = size_type(n - vacancies); size_type new_nodes = size_type(new_elems + get_block_size() - 1u)/get_block_size(); @@ -2348,7 +2845,8 @@ template deque(InputIterator, InputIterator, Allocator const&) -> deque::value_type, Allocator>; #endif -}} +} //namespace container +} //namespace boost #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED