Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/container for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: #ifndef BOOST_CONTAINER_DEQUE_HPP Chris@16: #define BOOST_CONTAINER_DEQUE_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@101: // container Chris@16: #include Chris@16: #include Chris@101: #include //new_allocator Chris@16: #include Chris@101: // container/detail Chris@101: #include Chris@101: #include //algo_equal(), algo_lexicographical_compare Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: // move Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: // move/detail Chris@101: #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@101: #include Chris@101: #endif Chris@101: #include Chris@101: // other Chris@101: #include Chris@101: #include Chris@101: // std Chris@16: #include Chris@101: Chris@101: #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) Chris@101: #include Chris@101: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace container { Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: template Chris@16: class deque; Chris@16: Chris@16: template Chris@16: struct deque_value_traits Chris@16: { Chris@16: typedef T value_type; Chris@101: static const bool trivial_dctr = container_detail::is_trivially_destructible::value; Chris@16: static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; Chris@16: }; Chris@16: Chris@16: // Note: this function is simply a kludge to work around several compilers' Chris@16: // bugs in handling constant expressions. Chris@16: template Chris@16: struct deque_buf_size Chris@16: { Chris@16: static const std::size_t min_size = 512u; Chris@16: static const std::size_t sizeof_t = sizeof(T); Chris@16: static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1); Chris@16: }; Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@16: // Class invariants: Chris@16: // For any nonsingular iterator i: Chris@16: // i.node is the address of an element in the map array. The Chris@16: // contents of i.node is a pointer to the beginning of a node. Chris@16: // i.first == //(i.node) Chris@16: // i.last == i.first + node_size Chris@16: // i.cur is a pointer in the range [i.first, i.last). NOTE: Chris@16: // the implication of this is that i.cur is always a dereferenceable Chris@16: // pointer, even if i is a past-the-end iterator. Chris@16: // Start and Finish are always nonsingular iterators. NOTE: this means Chris@16: // that an empty deque must have one node, and that a deque Chris@16: // with N elements, where N is the buffer size, must have two nodes. Chris@16: // For every node other than start.node and finish.node, every element Chris@16: // in the node is an initialized object. If start.node == finish.node, Chris@16: // then [start.cur, finish.cur) are initialized objects, and Chris@16: // the elements outside that range are uninitialized storage. Otherwise, Chris@16: // [start.cur, start.last) and [finish.first, finish.cur) are initialized Chris@16: // objects, and [start.first, start.cur) and [finish.cur, finish.last) Chris@16: // are uninitialized storage. Chris@101: // [map, map + map_size) is a valid, non-empty range. Chris@16: // [start.node, finish.node] is a valid range contained within Chris@101: // [map, map + map_size). Chris@101: // A pointer in the range [map, map + map_size) points to an allocated node Chris@16: // if and only if the pointer is in the range [start.node, finish.node]. Chris@16: template Chris@16: class deque_iterator Chris@16: { Chris@16: public: Chris@101: typedef std::random_access_iterator_tag iterator_category; Chris@16: typedef typename boost::intrusive::pointer_traits::element_type value_type; Chris@16: typedef typename boost::intrusive::pointer_traits::difference_type difference_type; Chris@16: typedef typename if_c Chris@16: < IsConst Chris@16: , typename boost::intrusive::pointer_traits::template Chris@16: rebind_pointer::type Chris@16: , Pointer Chris@16: >::type pointer; Chris@16: typedef typename if_c Chris@16: < IsConst Chris@16: , const value_type& Chris@16: , value_type& Chris@16: >::type reference; Chris@16: Chris@16: static std::size_t s_buffer_size() Chris@16: { return deque_buf_size::value; } Chris@16: Chris@16: typedef Pointer val_alloc_ptr; Chris@16: typedef typename boost::intrusive::pointer_traits:: Chris@101: template rebind_pointer::type index_pointer; Chris@16: Chris@16: Pointer m_cur; Chris@16: Pointer m_first; Chris@16: Pointer m_last; Chris@16: index_pointer m_node; Chris@16: Chris@16: public: Chris@16: Chris@16: Pointer get_cur() const { return m_cur; } Chris@16: Pointer get_first() const { return m_first; } Chris@16: Pointer get_last() const { return m_last; } Chris@16: index_pointer get_node() const { return m_node; } Chris@16: Chris@101: deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) Chris@16: {} Chris@16: Chris@101: deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW Chris@101: : m_cur(), m_first(), m_last(), m_node() //Value initialization to achieve "null iterators" (N3644) Chris@16: {} Chris@16: Chris@101: deque_iterator(deque_iterator const& x) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) Chris@16: {} Chris@16: Chris@101: deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: : m_cur(cur), m_first(first), m_last(last), m_node(node) Chris@16: {} Chris@16: Chris@101: deque_iterator unconst() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: return deque_iterator(this->get_cur(), this->get_first(), this->get_last(), this->get_node()); Chris@16: } Chris@16: Chris@101: reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *this->m_cur; } Chris@16: Chris@101: pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->m_cur; } Chris@16: Chris@101: difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if(!this->m_cur && !x.m_cur){ Chris@16: return 0; Chris@16: } Chris@16: return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + Chris@16: (this->m_cur - this->m_first) + (x.m_last - x.m_cur); Chris@16: } Chris@16: Chris@101: deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: ++this->m_cur; Chris@16: if (this->m_cur == this->m_last) { Chris@16: this->priv_set_node(this->m_node + 1); Chris@16: this->m_cur = this->m_first; Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@101: deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: deque_iterator tmp(*this); Chris@16: ++*this; Chris@16: return tmp; Chris@16: } Chris@16: Chris@101: deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if (this->m_cur == this->m_first) { Chris@16: this->priv_set_node(this->m_node - 1); Chris@16: this->m_cur = this->m_last; Chris@16: } Chris@16: --this->m_cur; Chris@16: return *this; Chris@16: } Chris@16: Chris@101: deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: deque_iterator tmp(*this); Chris@16: --*this; Chris@16: return tmp; Chris@16: } Chris@16: Chris@101: deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: difference_type offset = n + (this->m_cur - this->m_first); Chris@16: if (offset >= 0 && offset < difference_type(this->s_buffer_size())) Chris@16: this->m_cur += n; Chris@16: else { Chris@16: difference_type node_offset = Chris@16: offset > 0 ? offset / difference_type(this->s_buffer_size()) Chris@16: : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; Chris@16: this->priv_set_node(this->m_node + node_offset); Chris@16: this->m_cur = this->m_first + Chris@16: (offset - node_offset * difference_type(this->s_buffer_size())); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@101: deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { deque_iterator tmp(*this); return tmp += n; } Chris@16: Chris@101: deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *this += -n; } Chris@101: Chris@101: deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { deque_iterator tmp(*this); return tmp -= n; } Chris@16: Chris@101: reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *(*this + n); } Chris@16: Chris@101: friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return l.m_cur == r.m_cur; } Chris@16: Chris@101: friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return l.m_cur != r.m_cur; } Chris@16: Chris@101: friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } Chris@16: Chris@101: friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return r < l; } Chris@16: Chris@101: friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return !(r < l); } Chris@16: Chris@101: friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return !(l < r); } Chris@16: Chris@101: void priv_set_node(index_pointer new_node) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: this->m_node = new_node; Chris@16: this->m_first = *new_node; Chris@16: this->m_last = this->m_first + this->s_buffer_size(); Chris@16: } Chris@16: Chris@101: friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return x += n; } Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: Chris@16: // Deque base class. It has two purposes. First, its constructor Chris@16: // and destructor allocate (but don't initialize) storage. This makes Chris@16: // exception safety easier. Chris@16: template Chris@16: class deque_base Chris@16: { Chris@16: BOOST_COPYABLE_AND_MOVABLE(deque_base) Chris@16: public: Chris@16: typedef allocator_traits val_alloc_traits_type; Chris@16: typedef typename val_alloc_traits_type::value_type val_alloc_val; Chris@16: typedef typename val_alloc_traits_type::pointer val_alloc_ptr; Chris@16: typedef typename val_alloc_traits_type::const_pointer val_alloc_cptr; Chris@16: typedef typename val_alloc_traits_type::reference val_alloc_ref; Chris@16: typedef typename val_alloc_traits_type::const_reference val_alloc_cref; Chris@16: typedef typename val_alloc_traits_type::difference_type val_alloc_diff; Chris@16: typedef typename val_alloc_traits_type::size_type val_alloc_size; Chris@16: typedef typename val_alloc_traits_type::template Chris@16: portable_rebind_alloc::type ptr_alloc_t; Chris@16: typedef allocator_traits ptr_alloc_traits_type; Chris@16: typedef typename ptr_alloc_traits_type::value_type ptr_alloc_val; Chris@16: typedef typename ptr_alloc_traits_type::pointer ptr_alloc_ptr; Chris@16: typedef typename ptr_alloc_traits_type::const_pointer ptr_alloc_cptr; Chris@16: typedef typename ptr_alloc_traits_type::reference ptr_alloc_ref; Chris@16: typedef typename ptr_alloc_traits_type::const_reference ptr_alloc_cref; Chris@16: typedef Allocator allocator_type; Chris@16: typedef allocator_type stored_allocator_type; Chris@16: typedef val_alloc_size size_type; Chris@16: Chris@16: protected: Chris@16: Chris@16: typedef deque_value_traits traits_t; Chris@16: typedef ptr_alloc_t map_allocator_type; Chris@16: Chris@101: static size_type s_buffer_size() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return deque_buf_size::value; } Chris@16: Chris@16: val_alloc_ptr priv_allocate_node() Chris@16: { return this->alloc().allocate(s_buffer_size()); } Chris@16: Chris@101: void priv_deallocate_node(val_alloc_ptr p) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { this->alloc().deallocate(p, s_buffer_size()); } Chris@16: Chris@16: ptr_alloc_ptr priv_allocate_map(size_type n) Chris@16: { return this->ptr_alloc().allocate(n); } Chris@16: Chris@101: void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { this->ptr_alloc().deallocate(p, n); } Chris@16: Chris@16: typedef container_detail::deque_iterator iterator; Chris@16: typedef container_detail::deque_iterator const_iterator; Chris@16: Chris@16: deque_base(size_type num_elements, const allocator_type& a) Chris@16: : members_(a) Chris@16: { this->priv_initialize_map(num_elements); } Chris@16: Chris@16: explicit deque_base(const allocator_type& a) Chris@16: : members_(a) Chris@16: {} Chris@16: Chris@16: deque_base() Chris@16: : members_() Chris@16: {} Chris@16: Chris@16: explicit deque_base(BOOST_RV_REF(deque_base) x) Chris@16: : members_( boost::move(x.ptr_alloc()) Chris@16: , boost::move(x.alloc()) ) Chris@16: {} Chris@16: Chris@16: ~deque_base() Chris@16: { Chris@16: if (this->members_.m_map) { Chris@16: this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); Chris@16: this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: deque_base(const deque_base&); Chris@101: Chris@16: protected: Chris@16: Chris@101: void swap_members(deque_base &x) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@101: ::boost::adl_move_swap(this->members_.m_start, x.members_.m_start); Chris@101: ::boost::adl_move_swap(this->members_.m_finish, x.members_.m_finish); Chris@101: ::boost::adl_move_swap(this->members_.m_map, x.members_.m_map); Chris@101: ::boost::adl_move_swap(this->members_.m_map_size, x.members_.m_map_size); Chris@16: } Chris@16: Chris@16: void priv_initialize_map(size_type num_elements) Chris@16: { Chris@16: // if(num_elements){ Chris@16: size_type num_nodes = num_elements / s_buffer_size() + 1; Chris@16: Chris@16: this->members_.m_map_size = container_detail::max_value((size_type) InitialMapSize, num_nodes + 2); Chris@16: this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size); Chris@16: Chris@16: ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2; Chris@16: ptr_alloc_ptr nfinish = nstart + num_nodes; Chris@101: Chris@16: BOOST_TRY { Chris@16: this->priv_create_nodes(nstart, nfinish); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); Chris@16: this->members_.m_map = 0; Chris@16: this->members_.m_map_size = 0; Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: Chris@16: this->members_.m_start.priv_set_node(nstart); Chris@16: this->members_.m_finish.priv_set_node(nfinish - 1); Chris@16: this->members_.m_start.m_cur = this->members_.m_start.m_first; Chris@16: this->members_.m_finish.m_cur = this->members_.m_finish.m_first + Chris@16: num_elements % s_buffer_size(); Chris@16: // } Chris@16: } Chris@16: Chris@16: void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) Chris@16: { Chris@101: ptr_alloc_ptr cur = nstart; Chris@16: BOOST_TRY { Chris@101: for (; cur < nfinish; ++cur) Chris@16: *cur = this->priv_allocate_node(); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->priv_destroy_nodes(nstart, cur); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@101: void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) Chris@16: this->priv_deallocate_node(*n); Chris@16: } Chris@16: Chris@101: void priv_clear_map() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if (this->members_.m_map) { Chris@16: this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); Chris@16: this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); Chris@16: this->members_.m_map = 0; Chris@16: this->members_.m_map_size = 0; Chris@16: this->members_.m_start = iterator(); Chris@16: this->members_.m_finish = this->members_.m_start; Chris@16: } Chris@16: } Chris@16: Chris@16: enum { InitialMapSize = 8 }; Chris@16: Chris@16: protected: Chris@16: struct members_holder Chris@16: : public ptr_alloc_t Chris@16: , public allocator_type Chris@16: { Chris@16: members_holder() Chris@16: : map_allocator_type(), allocator_type() Chris@16: , m_map(0), m_map_size(0) Chris@16: , m_start(), m_finish(m_start) Chris@16: {} Chris@16: Chris@16: explicit members_holder(const allocator_type &a) Chris@16: : map_allocator_type(a), allocator_type(a) Chris@16: , m_map(0), m_map_size(0) Chris@16: , m_start(), m_finish(m_start) Chris@16: {} Chris@16: Chris@16: template Chris@16: members_holder(BOOST_FWD_REF(PtrAllocConvertible) pa, BOOST_FWD_REF(ValAllocConvertible) va) Chris@16: : map_allocator_type(boost::forward(pa)) Chris@16: , allocator_type (boost::forward(va)) Chris@16: , m_map(0), m_map_size(0) Chris@16: , m_start(), m_finish(m_start) Chris@16: {} Chris@16: Chris@16: ptr_alloc_ptr m_map; Chris@16: val_alloc_size m_map_size; Chris@16: iterator m_start; Chris@16: iterator m_finish; Chris@16: } members_; Chris@16: Chris@101: ptr_alloc_t &ptr_alloc() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return members_; } Chris@16: Chris@101: const ptr_alloc_t &ptr_alloc() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return members_; } Chris@101: Chris@101: allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { return members_; } Chris@101: Chris@101: const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return members_; } Chris@16: }; Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@101: #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@101: //! A double-ended queue is a sequence that supports random access to elements, constant time insertion Chris@101: //! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle. Chris@16: //! Chris@101: //! \tparam T The type of object that is stored in the deque Chris@101: //! \tparam Allocator The allocator used for all internal memory management Chris@101: template > Chris@16: #else Chris@16: template Chris@16: #endif Chris@16: class deque : protected deque_base Chris@16: { Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: private: Chris@16: typedef deque_base Base; Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // types Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@16: typedef T value_type; Chris@16: typedef typename ::boost::container::allocator_traits::pointer pointer; Chris@16: typedef typename ::boost::container::allocator_traits::const_pointer const_pointer; Chris@16: typedef typename ::boost::container::allocator_traits::reference reference; Chris@16: typedef typename ::boost::container::allocator_traits::const_reference const_reference; Chris@16: typedef typename ::boost::container::allocator_traits::size_type size_type; Chris@16: typedef typename ::boost::container::allocator_traits::difference_type difference_type; Chris@16: typedef Allocator allocator_type; Chris@16: typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; Chris@16: typedef BOOST_CONTAINER_IMPDEF(typename Base::iterator) iterator; Chris@16: typedef BOOST_CONTAINER_IMPDEF(typename Base::const_iterator) const_iterator; Chris@101: typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator) reverse_iterator; Chris@101: typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator) const_reverse_iterator; Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: private: // Internal typedefs Chris@16: BOOST_COPYABLE_AND_MOVABLE(deque) Chris@16: typedef typename Base::ptr_alloc_ptr index_pointer; Chris@16: static size_type s_buffer_size() Chris@16: { return Base::s_buffer_size(); } Chris@16: typedef allocator_traits allocator_traits_type; Chris@16: Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // construct/copy/destroy Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@16: //! Effects: Default constructors a deque. Chris@16: //! Chris@16: //! Throws: If allocator_type's default constructor throws. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: deque() Chris@16: : Base() Chris@16: {} Chris@16: Chris@16: //! Effects: Constructs a deque taking the allocator as parameter. Chris@16: //! Chris@16: //! Throws: Nothing Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: explicit deque(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: : Base(a) Chris@16: {} Chris@16: Chris@101: //! Effects: Constructs a deque Chris@16: //! and inserts n value initialized values. Chris@16: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's value initialization throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: explicit deque(size_type n) Chris@16: : Base(n, allocator_type()) Chris@16: { Chris@101: container_detail::insert_value_initialized_n_proxy proxy; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); Chris@16: //deque_base will deallocate in case of exception... Chris@16: } Chris@16: Chris@101: //! Effects: Constructs a deque Chris@16: //! and inserts n default initialized values. Chris@16: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's default initialization or copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: //! Chris@16: //! Note: Non-standard extension Chris@16: deque(size_type n, default_init_t) Chris@16: : Base(n, allocator_type()) Chris@16: { Chris@101: container_detail::insert_default_initialized_n_proxy proxy; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); Chris@101: //deque_base will deallocate in case of exception... Chris@101: } Chris@101: Chris@101: //! Effects: Constructs a deque that will use a copy of allocator a Chris@101: //! and inserts n value initialized values. Chris@101: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's value initialization throws. Chris@101: //! Chris@101: //! Complexity: Linear to n. Chris@101: explicit deque(size_type n, const allocator_type &a) Chris@101: : Base(n, a) Chris@101: { Chris@101: container_detail::insert_value_initialized_n_proxy proxy; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); Chris@101: //deque_base will deallocate in case of exception... Chris@101: } Chris@101: Chris@101: //! Effects: Constructs a deque that will use a copy of allocator a Chris@101: //! and inserts n default initialized values. Chris@101: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's default initialization or copy constructor throws. Chris@101: //! Chris@101: //! Complexity: Linear to n. Chris@101: //! Chris@101: //! Note: Non-standard extension Chris@101: deque(size_type n, default_init_t, const allocator_type &a) Chris@101: : Base(n, a) Chris@101: { Chris@101: container_detail::insert_default_initialized_n_proxy proxy; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); Chris@16: //deque_base will deallocate in case of exception... Chris@16: } Chris@16: Chris@16: //! Effects: Constructs a deque that will use a copy of allocator a Chris@16: //! and inserts n copies of value. Chris@16: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: deque(size_type n, const value_type& value, Chris@16: const allocator_type& a = allocator_type()) Chris@16: : Base(n, a) Chris@16: { this->priv_fill_initialize(value); } Chris@16: Chris@16: //! Effects: Constructs a deque that will use a copy of allocator a Chris@16: //! and inserts a copy of the range [first, last) in the deque. Chris@16: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's constructor taking a dereferenced InIt throws. Chris@16: //! Chris@16: //! Complexity: Linear to the range [first, last). Chris@16: template Chris@16: deque(InIt first, InIt last, const allocator_type& a = allocator_type() Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !container_detail::is_convertible::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : Base(a) Chris@16: { Chris@101: this->priv_range_initialize(first, last); Chris@16: } Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) Chris@101: //! Effects: Constructs a deque that will use a copy of allocator a Chris@101: //! and inserts a copy of the range [il.begin(), il.end()) in the deque. Chris@101: //! Chris@101: //! Throws: If allocator_type's default constructor Chris@101: //! throws or T's constructor taking a dereferenced std::initializer_list iterator throws. Chris@101: //! Chris@101: //! Complexity: Linear to the range [il.begin(), il.end()). Chris@101: deque(std::initializer_list il, const allocator_type& a = allocator_type()) Chris@101: : Base(a) Chris@101: { Chris@101: this->priv_range_initialize(il.begin(), il.end()); Chris@101: } Chris@101: #endif Chris@101: Chris@16: //! Effects: Copy constructs a deque. Chris@16: //! Chris@16: //! Postcondition: x == *this. Chris@16: //! Chris@16: //! Complexity: Linear to the elements x contains. Chris@16: deque(const deque& x) Chris@16: : Base(allocator_traits_type::select_on_container_copy_construction(x.alloc())) Chris@16: { Chris@16: if(x.size()){ Chris@16: this->priv_initialize_map(x.size()); Chris@16: boost::container::uninitialized_copy_alloc Chris@16: (this->alloc(), x.begin(), x.end(), this->members_.m_start); Chris@16: } Chris@16: } Chris@16: Chris@101: //! Effects: Move constructor. Moves x's resources to *this. Chris@16: //! Chris@16: //! Throws: If allocator_type's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: deque(BOOST_RV_REF(deque) x) Chris@101: : Base(BOOST_MOVE_BASE(Base, x)) Chris@16: { this->swap_members(x); } Chris@16: Chris@16: //! Effects: Copy constructs a vector using the specified allocator. Chris@16: //! Chris@16: //! Postcondition: x == *this. Chris@16: //! Chris@16: //! Throws: If allocation Chris@16: //! throws or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to the elements x contains. Chris@16: deque(const deque& x, const allocator_type &a) Chris@16: : Base(a) Chris@16: { Chris@16: if(x.size()){ Chris@16: this->priv_initialize_map(x.size()); Chris@16: boost::container::uninitialized_copy_alloc Chris@16: (this->alloc(), x.begin(), x.end(), this->members_.m_start); Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Move constructor using the specified allocator. Chris@101: //! Moves x's resources to *this if a == allocator_type(). Chris@16: //! Otherwise copies values from x to *this. Chris@16: //! Chris@16: //! Throws: If allocation or T's copy constructor throws. Chris@16: //! Chris@101: //! Complexity: Constant if a == x.get_allocator(), linear otherwise. Chris@101: deque(BOOST_RV_REF(deque) x, const allocator_type &a) Chris@16: : Base(a) Chris@16: { Chris@101: if(x.alloc() == a){ Chris@101: this->swap_members(x); Chris@16: } Chris@16: else{ Chris@101: if(x.size()){ Chris@101: this->priv_initialize_map(x.size()); Chris@16: boost::container::uninitialized_copy_alloc Chris@101: ( this->alloc(), boost::make_move_iterator(x.begin()) Chris@101: , boost::make_move_iterator(x.end()), this->members_.m_start); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Destroys the deque. All stored values are destroyed Chris@16: //! and used memory is deallocated. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Linear to the number of elements. Chris@101: ~deque() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: this->priv_destroy_range(this->members_.m_start, this->members_.m_finish); Chris@16: } Chris@16: Chris@16: //! Effects: Makes *this contain the same elements as x. Chris@16: //! Chris@16: //! Postcondition: this->size() == x.size(). *this contains a copy Chris@16: //! of each of x's elements. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to the number of elements in x. Chris@16: deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x) Chris@16: { Chris@16: if (&x != this){ Chris@16: allocator_type &this_alloc = this->alloc(); Chris@16: const allocator_type &x_alloc = x.alloc(); Chris@16: container_detail::bool_ flag; Chris@16: if(flag && this_alloc != x_alloc){ Chris@16: this->clear(); Chris@16: this->shrink_to_fit(); Chris@16: } Chris@16: container_detail::assign_alloc(this->alloc(), x.alloc(), flag); Chris@16: container_detail::assign_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); Chris@16: this->assign(x.cbegin(), x.cend()); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@101: //! Effects: Move assignment. All x's values are transferred to *this. Chris@16: //! Chris@101: //! Throws: If allocator_traits_type::propagate_on_container_move_assignment Chris@101: //! is false and (allocation throws or value_type's move constructor throws) Chris@16: //! Chris@101: //! Complexity: Constant if allocator_traits_type:: Chris@101: //! propagate_on_container_move_assignment is true or Chris@101: //! this->get>allocator() == x.get_allocator(). Linear otherwise. Chris@16: deque& operator= (BOOST_RV_REF(deque) x) Chris@101: BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value Chris@101: || allocator_traits_type::is_always_equal::value) Chris@16: { Chris@101: BOOST_ASSERT(this != &x); Chris@101: allocator_type &this_alloc = this->alloc(); Chris@101: allocator_type &x_alloc = x.alloc(); Chris@101: const bool propagate_alloc = allocator_traits_type:: Chris@101: propagate_on_container_move_assignment::value; Chris@101: container_detail::bool_ flag; Chris@101: const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; Chris@101: //Resources can be transferred if both allocators are Chris@101: //going to be equal after this function (either propagated or already equal) Chris@101: if(propagate_alloc || allocators_equal){ Chris@101: //Destroy objects but retain memory in case x reuses it in the future Chris@101: this->clear(); Chris@101: //Move allocator if needed Chris@101: container_detail::move_alloc(this_alloc, x_alloc, flag); Chris@101: container_detail::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); Chris@101: //Nothrow swap Chris@101: this->swap_members(x); Chris@101: } Chris@101: //Else do a one by one move Chris@101: else{ Chris@101: this->assign( boost::make_move_iterator(x.begin()) Chris@101: , boost::make_move_iterator(x.end())); Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) Chris@101: //! Effects: Makes *this contain the same elements as il. Chris@101: //! Chris@101: //! Postcondition: this->size() == il.size(). *this contains a copy Chris@101: //! of each of x's elements. Chris@101: //! Chris@101: //! Throws: If memory allocation throws or T's copy constructor throws. Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in il. Chris@101: deque& operator=(std::initializer_list il) Chris@101: { Chris@101: this->assign(il.begin(), il.end()); Chris@101: return *this; Chris@101: } Chris@101: #endif Chris@101: Chris@16: //! Effects: Assigns the n copies of val to *this. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: void assign(size_type n, const T& val) Chris@16: { Chris@16: typedef constant_iterator c_it; Chris@16: this->assign(c_it(val, n), c_it()); Chris@16: } Chris@16: Chris@16: //! Effects: Assigns the the range [first, last) to *this. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or Chris@16: //! T's constructor from dereferencing InIt throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: template Chris@16: void assign(InIt first, InIt last Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !container_detail::is_convertible::value Chris@16: && container_detail::is_input_iterator::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: { Chris@16: iterator cur = this->begin(); Chris@16: for ( ; first != last && cur != end(); ++cur, ++first){ Chris@16: *cur = *first; Chris@16: } Chris@16: if (first == last){ Chris@16: this->erase(cur, this->cend()); Chris@16: } Chris@16: else{ Chris@16: this->insert(this->cend(), first, last); Chris@16: } Chris@16: } Chris@16: Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: template Chris@16: void assign(FwdIt first, FwdIt last Chris@16: , typename container_detail::enable_if_c Chris@16: < !container_detail::is_convertible::value Chris@16: && !container_detail::is_input_iterator::value Chris@16: >::type * = 0 Chris@16: ) Chris@16: { Chris@101: const size_type len = boost::container::iterator_distance(first, last); Chris@16: if (len > size()) { Chris@16: FwdIt mid = first; Chris@101: boost::container::iterator_advance(mid, this->size()); Chris@16: boost::container::copy(first, mid, begin()); Chris@16: this->insert(this->cend(), mid, last); Chris@16: } Chris@16: else{ Chris@16: this->erase(boost::container::copy(first, last, this->begin()), cend()); Chris@16: } Chris@16: } Chris@16: #endif Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) Chris@101: //! Effects: Assigns the the range [il.begin(), il.end()) to *this. Chris@101: //! Chris@101: //! Throws: If memory allocation throws or Chris@101: //! T's constructor from dereferencing std::initializer_list iterator throws. Chris@101: //! Chris@101: //! Complexity: Linear to il.size(). Chris@101: void assign(std::initializer_list il) Chris@101: { this->assign(il.begin(), il.end()); } Chris@101: #endif Chris@101: Chris@16: //! Effects: Returns a copy of the internal allocator. Chris@16: //! Chris@16: //! Throws: If allocator's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return Base::alloc(); } Chris@16: Chris@16: //! Effects: Returns a reference to the internal allocator. Chris@16: //! Chris@16: //! Throws: Nothing Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: //! Chris@16: //! Note: Non-standard extension. Chris@101: const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return Base::alloc(); } Chris@16: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // iterators Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@16: //! Effects: Returns a reference to the internal allocator. Chris@16: //! Chris@16: //! Throws: Nothing Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: //! Chris@16: //! Note: Non-standard extension. Chris@101: stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return Base::alloc(); } Chris@16: Chris@16: //! Effects: Returns an iterator to the first element contained in the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: iterator begin() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_start; } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the first element contained in the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_start; } Chris@16: Chris@16: //! Effects: Returns an iterator to the end of the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: iterator end() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_finish; } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the end of the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_finish; } Chris@16: Chris@16: //! Effects: Returns a reverse_iterator pointing to the beginning Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return reverse_iterator(this->members_.m_finish); } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the beginning Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return const_reverse_iterator(this->members_.m_finish); } Chris@16: Chris@16: //! Effects: Returns a reverse_iterator pointing to the end Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return reverse_iterator(this->members_.m_start); } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the end Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return const_reverse_iterator(this->members_.m_start); } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the first element contained in the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_start; } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the end of the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_finish; } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the beginning Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return const_reverse_iterator(this->members_.m_finish); } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the end Chris@16: //! of the reversed deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return const_reverse_iterator(this->members_.m_start); } Chris@16: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // capacity Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@16: //! Effects: Returns true if the deque contains no elements. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: bool empty() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_finish == this->members_.m_start; } Chris@16: Chris@16: //! Effects: Returns the number of the elements contained in the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: size_type size() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_finish - this->members_.m_start; } Chris@16: Chris@16: //! Effects: Returns the largest possible size of the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return allocator_traits_type::max_size(this->alloc()); } Chris@16: Chris@16: //! Effects: Inserts or erases elements at the end such that Chris@16: //! the size becomes n. New elements are value initialized. Chris@16: //! Chris@16: //! Throws: If memory allocation throws, or T's constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to the difference between size() and new_size. Chris@16: void resize(size_type new_size) Chris@16: { Chris@16: const size_type len = size(); Chris@16: if (new_size < len) Chris@16: this->priv_erase_last_n(len - new_size); Chris@16: else{ Chris@16: const size_type n = new_size - this->size(); Chris@101: container_detail::insert_value_initialized_n_proxy proxy; Chris@16: priv_insert_back_aux_impl(n, proxy); Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Inserts or erases elements at the end such that Chris@16: //! the size becomes n. New elements are default initialized. Chris@16: //! Chris@16: //! Throws: If memory allocation throws, or T's constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to the difference between size() and new_size. Chris@16: //! Chris@16: //! Note: Non-standard extension Chris@16: void resize(size_type new_size, default_init_t) Chris@16: { Chris@16: const size_type len = size(); Chris@16: if (new_size < len) Chris@16: this->priv_erase_last_n(len - new_size); Chris@16: else{ Chris@16: const size_type n = new_size - this->size(); Chris@101: container_detail::insert_default_initialized_n_proxy proxy; Chris@16: priv_insert_back_aux_impl(n, proxy); Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Inserts or erases elements at the end such that Chris@16: //! the size becomes n. New elements are copy constructed from x. Chris@16: //! Chris@16: //! Throws: If memory allocation throws, or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to the difference between size() and new_size. Chris@16: void resize(size_type new_size, const value_type& x) Chris@16: { Chris@16: const size_type len = size(); Chris@16: if (new_size < len) Chris@16: this->erase(this->members_.m_start + new_size, this->members_.m_finish); Chris@16: else Chris@16: this->insert(this->members_.m_finish, new_size - len, x); Chris@16: } Chris@16: Chris@16: //! Effects: Tries to deallocate the excess of memory created Chris@16: //! with previous allocations. The size of the deque is unchanged Chris@16: //! Chris@16: //! Throws: If memory allocation throws. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: void shrink_to_fit() Chris@16: { Chris@16: //This deque implementation already Chris@16: //deallocates excess nodes when erasing Chris@16: //so there is nothing to do except for Chris@16: //empty deque Chris@16: if(this->empty()){ Chris@16: this->priv_clear_map(); Chris@16: } Chris@16: } Chris@16: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // element access Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@16: //! Requires: !empty() Chris@16: //! Chris@16: //! Effects: Returns a reference to the first Chris@16: //! element of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: reference front() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *this->members_.m_start; } Chris@16: Chris@16: //! Requires: !empty() Chris@16: //! Chris@16: //! Effects: Returns a const reference to the first element Chris@16: //! from the beginning of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *this->members_.m_start; } Chris@16: Chris@16: //! Requires: !empty() Chris@16: //! Chris@16: //! Effects: Returns a reference to the last Chris@16: //! element of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: reference back() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *(end()-1); } Chris@16: Chris@16: //! Requires: !empty() Chris@16: //! Chris@16: //! Effects: Returns a const reference to the last Chris@16: //! element of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return *(cend()-1); } Chris@16: Chris@16: //! Requires: size() > n. Chris@16: //! Chris@16: //! Effects: Returns a reference to the nth element Chris@16: //! from the beginning of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_start[difference_type(n)]; } Chris@16: Chris@16: //! Requires: size() > n. Chris@16: //! Chris@16: //! Effects: Returns a const reference to the nth element Chris@16: //! from the beginning of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@101: const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { return this->members_.m_start[difference_type(n)]; } Chris@16: Chris@101: //! Requires: size() >= n. Chris@101: //! Chris@101: //! Effects: Returns an iterator to the nth element Chris@101: //! from the beginning of the container. Returns end() Chris@101: //! if n == size(). Chris@101: //! Chris@101: //! Throws: Nothing. Chris@101: //! Chris@101: //! Complexity: Constant. Chris@101: //! Chris@101: //! Note: Non-standard extension Chris@101: iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { Chris@101: BOOST_ASSERT(this->size() >= n); Chris@101: return iterator(this->begin()+n); Chris@101: } Chris@101: Chris@101: //! Requires: size() >= n. Chris@101: //! Chris@101: //! Effects: Returns a const_iterator to the nth element Chris@101: //! from the beginning of the container. Returns end() Chris@101: //! if n == size(). Chris@101: //! Chris@101: //! Throws: Nothing. Chris@101: //! Chris@101: //! Complexity: Constant. Chris@101: //! Chris@101: //! Note: Non-standard extension Chris@101: const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { Chris@101: BOOST_ASSERT(this->size() >= n); Chris@101: return const_iterator(this->cbegin()+n); Chris@101: } Chris@101: Chris@101: //! Requires: size() >= n. Chris@101: //! Chris@101: //! Effects: Returns an iterator to the nth element Chris@101: //! from the beginning of the container. Returns end() Chris@101: //! if n == size(). Chris@101: //! Chris@101: //! Throws: Nothing. Chris@101: //! Chris@101: //! Complexity: Constant. Chris@101: //! Chris@101: //! Note: Non-standard extension Chris@101: size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { return this->priv_index_of(p); } Chris@101: Chris@101: //! Requires: begin() <= p <= end(). Chris@101: //! Chris@101: //! Effects: Returns the index of the element pointed by p Chris@101: //! and size() if p == end(). Chris@101: //! Chris@101: //! Throws: Nothing. Chris@101: //! Chris@101: //! Complexity: Constant. Chris@101: //! Chris@101: //! Note: Non-standard extension Chris@101: size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW Chris@101: { return this->priv_index_of(p); } Chris@101: Chris@16: //! Requires: size() > n. Chris@16: //! Chris@16: //! Effects: Returns a reference to the nth element Chris@16: //! from the beginning of the container. Chris@16: //! Chris@16: //! Throws: std::range_error if n >= size() Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: reference at(size_type n) Chris@16: { this->priv_range_check(n); return (*this)[n]; } Chris@16: Chris@16: //! Requires: size() > n. Chris@16: //! Chris@16: //! Effects: Returns a const reference to the nth element Chris@16: //! from the beginning of the container. Chris@16: //! Chris@16: //! Throws: std::range_error if n >= size() Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: const_reference at(size_type n) const Chris@16: { this->priv_range_check(n); return (*this)[n]; } Chris@16: Chris@16: ////////////////////////////////////////////// Chris@16: // Chris@16: // modifiers Chris@16: // Chris@16: ////////////////////////////////////////////// Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@16: //! Effects: Inserts an object of type T constructed with Chris@16: //! std::forward(args)... in the beginning of the deque. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or the in-place constructor throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time Chris@16: template Chris@101: void emplace_front(BOOST_FWD_REF(Args)... args) Chris@16: { Chris@16: if(this->priv_push_front_simple_available()){ Chris@16: allocator_traits_type::construct Chris@16: ( this->alloc() Chris@16: , this->priv_push_front_simple_pos() Chris@16: , boost::forward(args)...); Chris@16: this->priv_push_front_simple_commit(); Chris@16: } Chris@16: else{ Chris@101: typedef container_detail::insert_nonmovable_emplace_proxy type; Chris@101: this->priv_insert_front_aux_impl(1, type(boost::forward(args)...)); Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Inserts an object of type T constructed with Chris@16: //! std::forward(args)... in the end of the deque. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or the in-place constructor throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time Chris@16: template Chris@101: void emplace_back(BOOST_FWD_REF(Args)... args) Chris@16: { Chris@16: if(this->priv_push_back_simple_available()){ Chris@16: allocator_traits_type::construct Chris@16: ( this->alloc() Chris@16: , this->priv_push_back_simple_pos() Chris@16: , boost::forward(args)...); Chris@16: this->priv_push_back_simple_commit(); Chris@16: } Chris@16: else{ Chris@101: typedef container_detail::insert_nonmovable_emplace_proxy type; Chris@101: this->priv_insert_back_aux_impl(1, type(boost::forward(args)...)); Chris@16: } Chris@16: } Chris@16: Chris@101: //! Requires: p must be a valid iterator of *this. Chris@16: //! Chris@16: //! Effects: Inserts an object of type T constructed with Chris@101: //! std::forward(args)... before p Chris@16: //! Chris@16: //! Throws: If memory allocation throws or the in-place constructor throws. Chris@16: //! Chris@101: //! Complexity: If p is end(), amortized constant time Chris@16: //! Linear time otherwise. Chris@16: template Chris@101: iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) Chris@16: { Chris@16: if(p == this->cbegin()){ Chris@16: this->emplace_front(boost::forward(args)...); Chris@16: return this->begin(); Chris@16: } Chris@16: else if(p == this->cend()){ Chris@16: this->emplace_back(boost::forward(args)...); Chris@16: return (this->end()-1); Chris@16: } Chris@16: else{ Chris@16: typedef container_detail::insert_emplace_proxy type; Chris@101: return this->priv_insert_aux_impl(p, 1, type(boost::forward(args)...)); Chris@16: } Chris@16: } Chris@16: Chris@101: #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@101: #define BOOST_CONTAINER_DEQUE_EMPLACE_CODE(N) \ Chris@101: BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ Chris@101: void emplace_front(BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: if(priv_push_front_simple_available()){\ Chris@101: allocator_traits_type::construct\ Chris@101: ( this->alloc(), this->priv_push_front_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ Chris@101: priv_push_front_simple_commit();\ Chris@101: }\ Chris@101: else{\ Chris@101: typedef container_detail::insert_nonmovable_emplace_proxy##N\ Chris@101: type;\ Chris@101: priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\ Chris@101: }\ Chris@101: }\ Chris@101: \ Chris@101: BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ Chris@101: void emplace_back(BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: if(priv_push_back_simple_available()){\ Chris@101: allocator_traits_type::construct\ Chris@101: ( this->alloc(), this->priv_push_back_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ Chris@101: priv_push_back_simple_commit();\ Chris@101: }\ Chris@101: else{\ Chris@101: typedef container_detail::insert_nonmovable_emplace_proxy##N\ Chris@101: type;\ Chris@101: priv_insert_back_aux_impl(1, type(BOOST_MOVE_FWD##N));\ Chris@101: }\ Chris@101: }\ Chris@101: \ Chris@101: BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ Chris@101: iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ Chris@101: {\ Chris@101: if(p == this->cbegin()){\ Chris@101: this->emplace_front(BOOST_MOVE_FWD##N);\ Chris@101: return this->begin();\ Chris@101: }\ Chris@101: else if(p == cend()){\ Chris@101: this->emplace_back(BOOST_MOVE_FWD##N);\ Chris@101: return (--this->end());\ Chris@101: }\ Chris@101: else{\ Chris@101: typedef container_detail::insert_emplace_proxy_arg##N\ Chris@101: type;\ Chris@101: return this->priv_insert_aux_impl(p, 1, type(BOOST_MOVE_FWD##N));\ Chris@101: }\ Chris@101: } Chris@101: // Chris@101: BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEQUE_EMPLACE_CODE) Chris@101: #undef BOOST_CONTAINER_DEQUE_EMPLACE_CODE Chris@16: Chris@101: #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) Chris@16: Chris@16: #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: //! Effects: Inserts a copy of x at the front of the deque. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or Chris@16: //! T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time. Chris@16: void push_front(const T &x); Chris@16: Chris@16: //! Effects: Constructs a new element in the front of the deque Chris@101: //! and moves the resources of x to this new element. Chris@16: //! Chris@16: //! Throws: If memory allocation throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time. Chris@16: void push_front(T &&x); Chris@16: #else Chris@16: BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) Chris@16: #endif Chris@16: Chris@16: #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: //! Effects: Inserts a copy of x at the end of the deque. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or Chris@16: //! T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time. Chris@16: void push_back(const T &x); Chris@16: Chris@16: //! Effects: Constructs a new element in the end of the deque Chris@101: //! and moves the resources of x to this new element. Chris@16: //! Chris@16: //! Throws: If memory allocation throws. Chris@16: //! Chris@16: //! Complexity: Amortized constant time. Chris@16: void push_back(T &&x); Chris@16: #else Chris@16: BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) Chris@16: #endif Chris@16: Chris@16: #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: Chris@101: //! Requires: p must be a valid iterator of *this. Chris@16: //! Chris@101: //! Effects: Insert a copy of x before p. Chris@16: //! Chris@16: //! Returns: an iterator to the inserted element. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or x's copy constructor throws. Chris@16: //! Chris@101: //! Complexity: If p is end(), amortized constant time Chris@16: //! Linear time otherwise. Chris@101: iterator insert(const_iterator p, const T &x); Chris@16: Chris@101: //! Requires: p must be a valid iterator of *this. Chris@16: //! Chris@101: //! Effects: Insert a new element before p with x's resources. Chris@16: //! Chris@16: //! Returns: an iterator to the inserted element. Chris@16: //! Chris@16: //! Throws: If memory allocation throws. Chris@16: //! Chris@101: //! Complexity: If p is end(), amortized constant time Chris@16: //! Linear time otherwise. Chris@101: iterator insert(const_iterator p, T &&x); Chris@16: #else Chris@16: BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) Chris@16: #endif Chris@16: Chris@16: //! Requires: pos must be a valid iterator of *this. Chris@16: //! Chris@16: //! Effects: Insert n copies of x before pos. Chris@16: //! Chris@16: //! Returns: an iterator to the first inserted element or pos if n is 0. Chris@16: //! Chris@16: //! Throws: If memory allocation throws or T's copy constructor throws. Chris@16: //! Chris@16: //! Complexity: Linear to n. Chris@16: iterator insert(const_iterator pos, size_type n, const value_type& x) Chris@16: { Chris@16: typedef constant_iterator c_it; Chris@16: return this->insert(pos, c_it(x, n), c_it()); Chris@16: } Chris@16: Chris@16: //! Requires: pos must be a valid iterator of *this. Chris@16: //! Chris@16: //! Effects: Insert a copy of the [first, last) range before pos. Chris@16: //! Chris@16: //! Returns: an iterator to the first inserted element or pos if first == last. Chris@16: //! Chris@16: //! Throws: If memory allocation throws, T's constructor from a Chris@16: //! dereferenced InIt throws or T's copy constructor throws. Chris@16: //! Chris@101: //! Complexity: Linear to distance [first, last). Chris@16: template Chris@16: iterator insert(const_iterator pos, InIt first, InIt last Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !container_detail::is_convertible::value Chris@16: && container_detail::is_input_iterator::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: { Chris@16: size_type n = 0; Chris@16: iterator it(pos.unconst()); Chris@16: for(;first != last; ++first, ++n){ Chris@16: it = this->emplace(it, *first); Chris@16: ++it; Chris@16: } Chris@16: it -= n; Chris@16: return it; Chris@16: } Chris@16: Chris@101: #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) Chris@101: //! Requires: pos must be a valid iterator of *this. Chris@101: //! Chris@101: //! Effects: Insert a copy of the [il.begin(), il.end()) range before pos. Chris@101: //! Chris@101: //! Returns: an iterator to the first inserted element or pos if il.begin() == il.end(). Chris@101: //! Chris@101: //! Throws: If memory allocation throws, T's constructor from a Chris@101: //! dereferenced std::initializer_list throws or T's copy constructor throws. Chris@101: //! Chris@101: //! Complexity: Linear to distance [il.begin(), il.end()). Chris@101: iterator insert(const_iterator pos, std::initializer_list il) Chris@101: { return insert(pos, il.begin(), il.end()); } Chris@101: #endif Chris@101: Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: template Chris@16: iterator insert(const_iterator p, FwdIt first, FwdIt last Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !container_detail::is_convertible::value Chris@16: && !container_detail::is_input_iterator::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: { Chris@101: container_detail::insert_range_proxy proxy(first); Chris@101: return priv_insert_aux_impl(p, boost::container::iterator_distance(first, last), proxy); Chris@16: } Chris@16: #endif Chris@16: Chris@16: //! Effects: Removes the first element from the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant time. Chris@101: void pop_front() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { Chris@16: allocator_traits_type::destroy Chris@16: ( this->alloc() Chris@16: , container_detail::to_raw_pointer(this->members_.m_start.m_cur) Chris@16: ); Chris@16: ++this->members_.m_start.m_cur; Chris@16: } Chris@16: else Chris@16: this->priv_pop_front_aux(); Chris@16: } Chris@16: Chris@16: //! Effects: Removes the last element from the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant time. Chris@101: void pop_back() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { Chris@16: --this->members_.m_finish.m_cur; Chris@16: allocator_traits_type::destroy Chris@16: ( this->alloc() Chris@16: , container_detail::to_raw_pointer(this->members_.m_finish.m_cur) Chris@16: ); Chris@16: } Chris@16: else Chris@16: this->priv_pop_back_aux(); Chris@16: } Chris@16: Chris@101: //! Effects: Erases the element at p. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Linear to the elements between pos and the Chris@16: //! last element (if pos is near the end) or the first element Chris@16: //! if(pos is near the beginning). Chris@16: //! Constant if pos is the first or the last element. Chris@101: iterator erase(const_iterator pos) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: iterator next = pos.unconst(); Chris@16: ++next; Chris@16: size_type index = pos - this->members_.m_start; Chris@16: if (index < (this->size()/2)) { Chris@101: boost::container::move_backward(this->begin(), pos.unconst(), next); Chris@16: pop_front(); Chris@16: } Chris@16: else { Chris@101: boost::container::move(next, this->end(), pos.unconst()); Chris@16: pop_back(); Chris@16: } Chris@16: return this->members_.m_start + index; Chris@16: } Chris@16: Chris@16: //! Effects: Erases the elements pointed by [first, last). Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Linear to the distance between first and Chris@16: //! last plus the elements between pos and the Chris@16: //! last element (if pos is near the end) or the first element Chris@16: //! if(pos is near the beginning). Chris@101: iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: if (first == this->members_.m_start && last == this->members_.m_finish) { Chris@16: this->clear(); Chris@16: return this->members_.m_finish; Chris@16: } Chris@16: else { Chris@16: const size_type n = static_cast(last - first); Chris@16: const size_type elems_before = static_cast(first - this->members_.m_start); Chris@16: if (elems_before < (this->size() - n) - elems_before) { Chris@101: boost::container::move_backward(begin(), first.unconst(), last.unconst()); Chris@16: iterator new_start = this->members_.m_start + n; Chris@16: if(!Base::traits_t::trivial_dctr_after_move) Chris@16: this->priv_destroy_range(this->members_.m_start, new_start); Chris@16: this->priv_destroy_nodes(this->members_.m_start.m_node, new_start.m_node); Chris@16: this->members_.m_start = new_start; Chris@16: } Chris@16: else { Chris@101: boost::container::move(last.unconst(), end(), first.unconst()); Chris@16: iterator new_finish = this->members_.m_finish - n; Chris@16: if(!Base::traits_t::trivial_dctr_after_move) Chris@16: this->priv_destroy_range(new_finish, this->members_.m_finish); Chris@16: this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1); Chris@16: this->members_.m_finish = new_finish; Chris@16: } Chris@16: return this->members_.m_start + elems_before; Chris@16: } Chris@16: } Chris@16: Chris@16: //! Effects: Swaps the contents of *this and x. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: void swap(deque &x) Chris@101: BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value Chris@101: || allocator_traits_type::is_always_equal::value) Chris@16: { Chris@16: this->swap_members(x); Chris@16: container_detail::bool_ flag; Chris@16: container_detail::swap_alloc(this->alloc(), x.alloc(), flag); Chris@16: container_detail::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag); Chris@16: } Chris@16: Chris@16: //! Effects: Erases all the elements of the deque. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Linear to the number of elements in the deque. Chris@101: void clear() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: for (index_pointer node = this->members_.m_start.m_node + 1; Chris@16: node < this->members_.m_finish.m_node; Chris@16: ++node) { Chris@16: this->priv_destroy_range(*node, *node + this->s_buffer_size()); Chris@16: this->priv_deallocate_node(*node); Chris@16: } Chris@16: Chris@16: if (this->members_.m_start.m_node != this->members_.m_finish.m_node) { Chris@16: this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last); Chris@16: this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur); Chris@16: this->priv_deallocate_node(this->members_.m_finish.m_first); Chris@16: } Chris@16: else Chris@16: this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur); Chris@16: Chris@16: this->members_.m_finish = this->members_.m_start; Chris@16: } Chris@16: Chris@101: //! Effects: Returns true if x and y are equal Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator==(const deque& x, const deque& y) Chris@101: { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } Chris@101: Chris@101: //! Effects: Returns true if x and y are unequal Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator!=(const deque& x, const deque& y) Chris@101: { return !(x == y); } Chris@101: Chris@101: //! Effects: Returns true if x is less than y Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator<(const deque& x, const deque& y) Chris@101: { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } Chris@101: Chris@101: //! Effects: Returns true if x is greater than y Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator>(const deque& x, const deque& y) Chris@101: { return y < x; } Chris@101: Chris@101: //! Effects: Returns true if x is equal or less than y Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator<=(const deque& x, const deque& y) Chris@101: { return !(y < x); } Chris@101: Chris@101: //! Effects: Returns true if x is equal or greater than y Chris@101: //! Chris@101: //! Complexity: Linear to the number of elements in the container. Chris@101: friend bool operator>=(const deque& x, const deque& y) Chris@101: { return !(x < y); } Chris@101: Chris@101: //! Effects: x.swap(y) Chris@101: //! Chris@101: //! Complexity: Constant. Chris@101: friend void swap(deque& x, deque& y) Chris@101: { x.swap(y); } Chris@101: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: private: Chris@16: Chris@101: size_type priv_index_of(const_iterator p) const Chris@101: { Chris@101: BOOST_ASSERT(this->cbegin() <= p); Chris@101: BOOST_ASSERT(p <= this->cend()); Chris@101: return static_cast(p - this->cbegin()); Chris@101: } Chris@101: Chris@16: void priv_erase_last_n(size_type n) Chris@16: { Chris@16: if(n == this->size()) { Chris@16: this->clear(); Chris@16: } Chris@16: else { Chris@16: iterator new_finish = this->members_.m_finish - n; Chris@16: if(!Base::traits_t::trivial_dctr_after_move) Chris@16: this->priv_destroy_range(new_finish, this->members_.m_finish); Chris@16: this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1); Chris@16: this->members_.m_finish = new_finish; Chris@16: } Chris@16: } Chris@16: Chris@16: void priv_range_check(size_type n) const Chris@16: { if (n >= this->size()) throw_out_of_range("deque::at out of range"); } Chris@16: Chris@16: template Chris@101: iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x) Chris@16: { Chris@101: if (p == cbegin()){ Chris@16: this->push_front(::boost::forward(x)); Chris@16: return begin(); Chris@16: } Chris@101: else if (p == cend()){ Chris@16: this->push_back(::boost::forward(x)); Chris@16: return --end(); Chris@16: } Chris@16: else { Chris@16: return priv_insert_aux_impl Chris@101: ( p, (size_type)1 Chris@101: , container_detail::get_insert_value_proxy(::boost::forward(x))); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void priv_push_front(BOOST_FWD_REF(U) x) Chris@16: { Chris@16: if(this->priv_push_front_simple_available()){ Chris@16: allocator_traits_type::construct Chris@16: ( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward(x)); Chris@16: this->priv_push_front_simple_commit(); Chris@16: } Chris@16: else{ Chris@16: priv_insert_aux_impl Chris@101: ( this->cbegin(), (size_type)1 Chris@101: , container_detail::get_insert_value_proxy(::boost::forward(x))); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void priv_push_back(BOOST_FWD_REF(U) x) Chris@16: { Chris@16: if(this->priv_push_back_simple_available()){ Chris@16: allocator_traits_type::construct Chris@16: ( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward(x)); Chris@16: this->priv_push_back_simple_commit(); Chris@16: } Chris@16: else{ Chris@16: priv_insert_aux_impl Chris@101: ( this->cend(), (size_type)1 Chris@101: , container_detail::get_insert_value_proxy(::boost::forward(x))); Chris@16: } Chris@16: } Chris@16: Chris@16: bool priv_push_back_simple_available() const Chris@16: { Chris@16: return this->members_.m_map && Chris@16: (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1)); Chris@16: } Chris@16: Chris@16: T *priv_push_back_simple_pos() const Chris@16: { Chris@16: return container_detail::to_raw_pointer(this->members_.m_finish.m_cur); Chris@16: } Chris@16: Chris@16: void priv_push_back_simple_commit() Chris@16: { Chris@16: ++this->members_.m_finish.m_cur; Chris@16: } Chris@16: Chris@16: bool priv_push_front_simple_available() const Chris@16: { Chris@16: return this->members_.m_map && Chris@16: (this->members_.m_start.m_cur != this->members_.m_start.m_first); Chris@16: } Chris@16: Chris@16: T *priv_push_front_simple_pos() const Chris@16: { return container_detail::to_raw_pointer(this->members_.m_start.m_cur) - 1; } Chris@16: Chris@16: void priv_push_front_simple_commit() Chris@16: { --this->members_.m_start.m_cur; } Chris@16: Chris@16: void priv_destroy_range(iterator p, iterator p2) Chris@16: { Chris@101: if(!Base::traits_t::trivial_dctr){ Chris@101: for(;p != p2; ++p){ Chris@101: allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); Chris@101: } Chris@16: } Chris@16: } Chris@16: Chris@16: void priv_destroy_range(pointer p, pointer p2) Chris@16: { Chris@101: if(!Base::traits_t::trivial_dctr){ Chris@101: for(;p != p2; ++p){ Chris@101: allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); Chris@101: } Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@101: iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy) Chris@16: { Chris@16: iterator pos(p.unconst()); Chris@16: const size_type pos_n = p - this->cbegin(); Chris@16: if(!this->members_.m_map){ Chris@16: this->priv_initialize_map(0); Chris@16: pos = this->begin(); Chris@16: } Chris@16: Chris@16: const size_type elemsbefore = static_cast(pos - this->members_.m_start); Chris@16: const size_type length = this->size(); Chris@16: if (elemsbefore < length / 2) { Chris@16: const iterator new_start = this->priv_reserve_elements_at_front(n); Chris@16: const iterator old_start = this->members_.m_start; Chris@16: if(!elemsbefore){ Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); Chris@16: this->members_.m_start = new_start; Chris@16: } Chris@16: else{ Chris@16: pos = this->members_.m_start + elemsbefore; Chris@16: if (elemsbefore >= n) { Chris@16: const iterator start_n = this->members_.m_start + n; Chris@16: ::boost::container::uninitialized_move_alloc Chris@16: (this->alloc(), this->members_.m_start, start_n, new_start); Chris@16: this->members_.m_start = new_start; Chris@101: boost::container::move(start_n, pos, old_start); Chris@101: proxy.copy_n_and_update(this->alloc(), pos - n, n); Chris@16: } Chris@16: else { Chris@16: const size_type mid_count = n - elemsbefore; Chris@16: const iterator mid_start = old_start - mid_count; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count); Chris@16: this->members_.m_start = mid_start; Chris@16: ::boost::container::uninitialized_move_alloc Chris@16: (this->alloc(), old_start, pos, new_start); Chris@16: this->members_.m_start = new_start; Chris@101: proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore); Chris@16: } Chris@16: } Chris@16: } Chris@16: else { Chris@16: const iterator new_finish = this->priv_reserve_elements_at_back(n); Chris@16: const iterator old_finish = this->members_.m_finish; Chris@16: const size_type elemsafter = length - elemsbefore; Chris@16: if(!elemsafter){ Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); Chris@16: this->members_.m_finish = new_finish; Chris@16: } Chris@16: else{ Chris@16: pos = old_finish - elemsafter; Chris@16: if (elemsafter >= n) { Chris@16: iterator finish_n = old_finish - difference_type(n); Chris@16: ::boost::container::uninitialized_move_alloc Chris@16: (this->alloc(), finish_n, old_finish, old_finish); Chris@16: this->members_.m_finish = new_finish; Chris@101: boost::container::move_backward(pos, finish_n, old_finish); Chris@101: proxy.copy_n_and_update(this->alloc(), pos, n); Chris@16: } Chris@16: else { Chris@16: const size_type raw_gap = n - elemsafter; Chris@16: ::boost::container::uninitialized_move_alloc Chris@16: (this->alloc(), pos, old_finish, old_finish + raw_gap); Chris@16: BOOST_TRY{ Chris@101: proxy.copy_n_and_update(this->alloc(), pos, elemsafter); Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->priv_destroy_range(old_finish, old_finish + elemsafter); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: this->members_.m_finish = new_finish; Chris@16: } Chris@16: } Chris@16: } Chris@16: return this->begin() + pos_n; Chris@16: } Chris@16: Chris@16: template Chris@101: iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy) Chris@16: { Chris@16: if(!this->members_.m_map){ Chris@16: this->priv_initialize_map(0); Chris@16: } Chris@16: Chris@16: iterator new_finish = this->priv_reserve_elements_at_back(n); Chris@16: iterator old_finish = this->members_.m_finish; Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n); Chris@16: this->members_.m_finish = new_finish; Chris@16: return iterator(this->members_.m_finish - n); Chris@16: } Chris@16: Chris@16: template Chris@101: iterator priv_insert_front_aux_impl(size_type n, InsertProxy proxy) Chris@16: { Chris@16: if(!this->members_.m_map){ Chris@16: this->priv_initialize_map(0); Chris@16: } Chris@16: Chris@16: iterator new_start = this->priv_reserve_elements_at_front(n); Chris@101: proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n); Chris@16: this->members_.m_start = new_start; Chris@16: return new_start; Chris@16: } Chris@16: Chris@16: iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x) Chris@16: { Chris@16: typedef constant_iterator c_it; Chris@16: return this->insert(pos, c_it(x, n), c_it()); Chris@16: } Chris@16: Chris@16: // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized, Chris@16: // but none of the deque's elements have yet been constructed. Chris@16: void priv_fill_initialize(const value_type& value) Chris@16: { Chris@101: index_pointer cur = this->members_.m_start.m_node; Chris@16: BOOST_TRY { Chris@101: for ( ; cur < this->members_.m_finish.m_node; ++cur){ Chris@16: boost::container::uninitialized_fill_alloc Chris@16: (this->alloc(), *cur, *cur + this->s_buffer_size(), value); Chris@16: } Chris@16: boost::container::uninitialized_fill_alloc Chris@16: (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: template Chris@101: typename iterator_enable_if_tag::type Chris@101: priv_range_initialize(InIt first, InIt last) Chris@16: { Chris@16: this->priv_initialize_map(0); Chris@16: BOOST_TRY { Chris@16: for ( ; first != last; ++first) Chris@16: this->emplace_back(*first); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->clear(); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: template Chris@101: typename iterator_disable_if_tag::type Chris@101: priv_range_initialize(FwdIt first, FwdIt last) Chris@16: { Chris@16: size_type n = 0; Chris@101: n = boost::container::iterator_distance(first, last); Chris@16: this->priv_initialize_map(n); Chris@16: Chris@101: index_pointer cur_node = this->members_.m_start.m_node; Chris@16: BOOST_TRY { Chris@101: for (; cur_node < this->members_.m_finish.m_node; ++cur_node) { Chris@16: FwdIt mid = first; Chris@101: boost::container::iterator_advance(mid, this->s_buffer_size()); Chris@16: ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node); Chris@16: first = mid; Chris@16: } Chris@16: ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. Chris@101: void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: this->priv_deallocate_node(this->members_.m_finish.m_first); Chris@16: this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); Chris@16: this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; Chris@16: allocator_traits_type::destroy Chris@16: ( this->alloc() Chris@16: , container_detail::to_raw_pointer(this->members_.m_finish.m_cur) Chris@16: ); Chris@16: } Chris@16: Chris@16: // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that Chris@16: // if the deque has at least one element (a precondition for this member Chris@16: // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque Chris@16: // must have at least two nodes. Chris@101: void priv_pop_front_aux() BOOST_NOEXCEPT_OR_NOTHROW Chris@16: { Chris@16: allocator_traits_type::destroy Chris@16: ( this->alloc() Chris@16: , container_detail::to_raw_pointer(this->members_.m_start.m_cur) Chris@16: ); Chris@16: this->priv_deallocate_node(this->members_.m_start.m_first); Chris@16: this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1); Chris@16: this->members_.m_start.m_cur = this->members_.m_start.m_first; Chris@101: } Chris@16: Chris@16: iterator priv_reserve_elements_at_front(size_type n) Chris@16: { Chris@16: size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first; Chris@16: if (n > vacancies){ Chris@16: size_type new_elems = n-vacancies; Chris@16: size_type new_nodes = (new_elems + this->s_buffer_size() - 1) / Chris@16: this->s_buffer_size(); Chris@16: size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map); Chris@16: if (new_nodes > s){ Chris@16: this->priv_reallocate_map(new_nodes, true); Chris@16: } Chris@16: size_type i = 1; Chris@16: BOOST_TRY { Chris@16: for (; i <= new_nodes; ++i) Chris@16: *(this->members_.m_start.m_node - i) = this->priv_allocate_node(); Chris@16: } Chris@16: BOOST_CATCH(...) { Chris@16: for (size_type j = 1; j < i; ++j) Chris@101: this->priv_deallocate_node(*(this->members_.m_start.m_node - j)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: return this->members_.m_start - difference_type(n); Chris@16: } Chris@16: Chris@16: iterator priv_reserve_elements_at_back(size_type n) Chris@16: { Chris@16: size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1; Chris@16: if (n > vacancies){ Chris@16: size_type new_elems = n - vacancies; Chris@16: size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size(); Chris@16: size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map)); Chris@16: if (new_nodes + 1 > s){ Chris@16: this->priv_reallocate_map(new_nodes, false); Chris@16: } Chris@101: size_type i = 1; Chris@16: BOOST_TRY { Chris@101: for (; i <= new_nodes; ++i) Chris@16: *(this->members_.m_finish.m_node + i) = this->priv_allocate_node(); Chris@16: } Chris@16: BOOST_CATCH(...) { Chris@16: for (size_type j = 1; j < i; ++j) Chris@101: this->priv_deallocate_node(*(this->members_.m_finish.m_node + j)); Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: return this->members_.m_finish + difference_type(n); Chris@16: } Chris@16: Chris@16: void priv_reallocate_map(size_type nodes_to_add, bool add_at_front) Chris@16: { Chris@16: size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1; Chris@16: size_type new_num_nodes = old_num_nodes + nodes_to_add; Chris@16: Chris@16: index_pointer new_nstart; Chris@16: if (this->members_.m_map_size > 2 * new_num_nodes) { Chris@16: new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 Chris@16: + (add_at_front ? nodes_to_add : 0); Chris@16: if (new_nstart < this->members_.m_start.m_node) Chris@101: boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); Chris@16: else Chris@101: boost::container::move_backward Chris@16: (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes); Chris@16: } Chris@16: else { Chris@16: size_type new_map_size = Chris@16: this->members_.m_map_size + container_detail::max_value(this->members_.m_map_size, nodes_to_add) + 2; Chris@16: Chris@16: index_pointer new_map = this->priv_allocate_map(new_map_size); Chris@16: new_nstart = new_map + (new_map_size - new_num_nodes) / 2 Chris@16: + (add_at_front ? nodes_to_add : 0); Chris@101: boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); Chris@16: this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); Chris@16: Chris@16: this->members_.m_map = new_map; Chris@16: this->members_.m_map_size = new_map_size; Chris@16: } Chris@16: Chris@16: this->members_.m_start.priv_set_node(new_nstart); Chris@16: this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1); Chris@16: } Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@16: }} Chris@16: Chris@101: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: //!has_trivial_destructor_after_move<> == true_type Chris@16: //!specialization for optimizations Chris@16: template Chris@16: struct has_trivial_destructor_after_move > Chris@101: { Chris@101: typedef typename ::boost::container::allocator_traits::pointer pointer; Chris@101: static const bool value = ::boost::has_trivial_destructor_after_move::value && Chris@101: ::boost::has_trivial_destructor_after_move::value; Chris@101: }; Chris@16: Chris@16: } Chris@16: Chris@101: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // #ifndef BOOST_CONTAINER_DEQUE_HPP