summaryrefslogtreecommitdiff
path: root/boost/container/stable_vector.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/stable_vector.hpp')
-rw-r--r--boost/container/stable_vector.hpp1818
1 files changed, 1818 insertions, 0 deletions
diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp
new file mode 100644
index 0000000000..851b5f26e8
--- /dev/null
+++ b/boost/container/stable_vector.hpp
@@ -0,0 +1,1818 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+// Stable vector.
+//
+// Copyright 2008 Joaquin M Lopez Munoz.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
+#define BOOST_CONTAINER_STABLE_VECTOR_HPP
+
+#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/container/detail/version_type.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/algorithms.hpp>
+#include <boost/container/allocator/allocator_traits.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+///@cond
+
+#include <boost/container/vector.hpp>
+
+//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+
+#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+#include <boost/assert.hpp>
+#endif
+
+///@endcond
+
+namespace boost {
+namespace container {
+
+///@cond
+
+namespace stable_vector_detail{
+
+template<class SmartPtr>
+struct smart_ptr_type
+{
+ typedef typename SmartPtr::value_type value_type;
+ typedef value_type *pointer;
+ static pointer get (const SmartPtr &smartptr)
+ { return smartptr.get();}
+};
+
+template<class T>
+struct smart_ptr_type<T*>
+{
+ typedef T value_type;
+ typedef value_type *pointer;
+ static pointer get (pointer ptr)
+ { return ptr;}
+};
+
+template<class Ptr>
+inline typename smart_ptr_type<Ptr>::pointer to_raw_pointer(const Ptr &ptr)
+{ return smart_ptr_type<Ptr>::get(ptr); }
+
+template <class C>
+class clear_on_destroy
+{
+ public:
+ clear_on_destroy(C &c)
+ : c_(c), do_clear_(true)
+ {}
+
+ void release()
+ { do_clear_ = false; }
+
+ ~clear_on_destroy()
+ {
+ if(do_clear_){
+ c_.clear();
+ c_.clear_pool();
+ }
+ }
+
+ private:
+ clear_on_destroy(const clear_on_destroy &);
+ clear_on_destroy &operator=(const clear_on_destroy &);
+ C &c_;
+ bool do_clear_;
+};
+
+template<class VoidPtr>
+struct node_type_base
+{/*
+ node_type_base(VoidPtr p)
+ : up(p)
+ {}*/
+ node_type_base()
+ {}
+ void set_pointer(VoidPtr p)
+ { up = p; }
+
+ VoidPtr up;
+};
+
+template<typename VoidPointer, typename T>
+struct node_type
+ : public node_type_base<VoidPointer>
+{
+ node_type()
+ : value()
+ {}
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ template<class ...Args>
+ node_type(Args &&...args)
+ : value(boost::forward<Args>(args)...)
+ {}
+
+ #else //BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ node_type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ : value(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \
+ {} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif//BOOST_CONTAINER_PERFECT_FORWARDING
+
+ void set_pointer(VoidPointer p)
+ { node_type_base<VoidPointer>::set_pointer(p); }
+
+ T value;
+};
+
+template<typename T, typename Reference, typename Pointer>
+class iterator
+ : public std::iterator< std::random_access_iterator_tag
+ , T
+ , typename boost::intrusive::
+ pointer_traits<Pointer>::difference_type
+ , Pointer
+ , Reference>
+{
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::template
+ rebind_pointer<void>::type void_ptr;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::template
+ rebind_pointer<const void>::type const_void_ptr;
+ typedef node_type<void_ptr, T> node_type_t;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::template
+ rebind_pointer<node_type_t>::type node_type_ptr_t;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::template
+ rebind_pointer<const node_type_t>::type const_node_type_ptr_t;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::template
+ rebind_pointer<void_ptr>::type void_ptr_ptr;
+
+ friend class iterator<T, const T, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>;
+
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef T value_type;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::difference_type difference_type;
+ typedef Pointer pointer;
+ typedef Reference reference;
+
+ iterator()
+ {}
+
+ explicit iterator(node_type_ptr_t pn)
+ : pn(pn)
+ {}
+
+ iterator(const iterator<T, T&, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>& x)
+ : pn(x.pn)
+ {}
+
+ private:
+ static node_type_ptr_t node_ptr_cast(const void_ptr &p)
+ {
+ return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
+ }
+
+ static const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p)
+ {
+ return const_node_type_ptr_t(static_cast<const node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
+ }
+
+ static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p)
+ {
+ return void_ptr_ptr(static_cast<void_ptr*>(stable_vector_detail::to_raw_pointer(p)));
+ }
+
+ reference dereference() const
+ { return pn->value; }
+ bool equal(const iterator& x) const
+ { return pn==x.pn; }
+ void increment()
+ { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+1)); }
+ void decrement()
+ { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)-1)); }
+ void advance(difference_type n)
+ { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+n)); }
+ difference_type distance_to(const iterator& x)const
+ { return void_ptr_ptr_cast(x.pn->up) - void_ptr_ptr_cast(pn->up); }
+
+ public:
+ //Pointer like operators
+ reference operator*() const { return this->dereference(); }
+ pointer operator->() const { return pointer(&this->dereference()); }
+
+ //Increment / Decrement
+ iterator& operator++()
+ { this->increment(); return *this; }
+
+ iterator operator++(int)
+ { iterator tmp(*this); ++*this; return iterator(tmp); }
+
+ iterator& operator--()
+ { this->decrement(); return *this; }
+
+ iterator operator--(int)
+ { iterator tmp(*this); --*this; return iterator(tmp); }
+
+ reference operator[](difference_type off) const
+ {
+ iterator tmp(*this);
+ tmp += off;
+ return *tmp;
+ }
+
+ iterator& operator+=(difference_type off)
+ {
+ pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+off));
+ return *this;
+ }
+
+ friend iterator operator+(const iterator &left, difference_type off)
+ {
+ iterator tmp(left);
+ tmp += off;
+ return tmp;
+ }
+
+ friend iterator operator+(difference_type off, const iterator& right)
+ {
+ iterator tmp(right);
+ tmp += off;
+ return tmp;
+ }
+
+ iterator& operator-=(difference_type off)
+ { *this += -off; return *this; }
+
+ friend iterator operator-(const iterator &left, difference_type off)
+ {
+ iterator tmp(left);
+ tmp -= off;
+ return tmp;
+ }
+
+ friend difference_type operator-(const iterator& left, const iterator& right)
+ {
+ return void_ptr_ptr_cast(left.pn->up) - void_ptr_ptr_cast(right.pn->up);
+ }
+
+ //Comparison operators
+ friend bool operator== (const iterator& l, const iterator& r)
+ { return l.pn == r.pn; }
+
+ friend bool operator!= (const iterator& l, const iterator& r)
+ { return l.pn != r.pn; }
+
+ friend bool operator< (const iterator& l, const iterator& r)
+ { return void_ptr_ptr_cast(l.pn->up) < void_ptr_ptr_cast(r.pn->up); }
+
+ friend bool operator<= (const iterator& l, const iterator& r)
+ { return void_ptr_ptr_cast(l.pn->up) <= void_ptr_ptr_cast(r.pn->up); }
+
+ friend bool operator> (const iterator& l, const iterator& r)
+ { return void_ptr_ptr_cast(l.pn->up) > void_ptr_ptr_cast(r.pn->up); }
+
+ friend bool operator>= (const iterator& l, const iterator& r)
+ { return void_ptr_ptr_cast(l.pn->up) >= void_ptr_ptr_cast(r.pn->up); }
+
+ node_type_ptr_t pn;
+};
+
+template<class A, unsigned int Version>
+struct select_multiallocation_chain
+{
+ typedef typename A::multiallocation_chain type;
+};
+
+template<class A>
+struct select_multiallocation_chain<A, 1>
+{
+ typedef typename boost::intrusive::pointer_traits
+ <typename allocator_traits<A>::pointer>::
+ template rebind_pointer<void>::type void_ptr;
+ typedef container_detail::basic_multiallocation_chain
+ <void_ptr> multialloc_cached_counted;
+ typedef boost::container::container_detail::
+ transform_multiallocation_chain
+ < multialloc_cached_counted
+ , typename allocator_traits<A>::value_type> type;
+};
+
+} //namespace stable_vector_detail
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+
+#define STABLE_VECTOR_CHECK_INVARIANT \
+invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
+BOOST_JOIN(check_invariant_,__LINE__).touch();
+#else
+
+#define STABLE_VECTOR_CHECK_INVARIANT
+
+#endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+
+#endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+/// @endcond
+
+//!Originally developed by Joaquin M. Lopez Munoz, stable_vector is std::vector
+//!drop-in replacement implemented as a node container, offering iterator and reference
+//!stability.
+//!
+//!More details taken the author's blog: (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" > Introducing stable_vector</a>)
+//!
+//!We present stable_vector, a fully STL-compliant stable container that provides
+//!most of the features of std::vector except element contiguity.
+//!
+//!General properties: stable_vector satisfies all the requirements of a container,
+//!a reversible container and a sequence and provides all the optional operations
+//!present in std::vector. Like std::vector, iterators are random access.
+//!stable_vector does not provide element contiguity; in exchange for this absence,
+//!the container is stable, i.e. references and iterators to an element of a stable_vector
+//!remain valid as long as the element is not erased, and an iterator that has been
+//!assigned the return value of end() always remain valid until the destruction of
+//!the associated stable_vector.
+//!
+//!Operation complexity: The big-O complexities of stable_vector operations match
+//!exactly those of std::vector. In general, insertion/deletion is constant time at
+//!the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector
+//!does not internally perform any value_type destruction, copy or assignment
+//!operations other than those exactly corresponding to the insertion of new
+//!elements or deletion of stored elements, which can sometimes compensate in terms
+//!of performance for the extra burden of doing more pointer manipulation and an
+//!additional allocation per element.
+//!
+//!Exception safety: As stable_vector does not internally copy elements around, some
+//!operations provide stronger exception safety guarantees than in std::vector:
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class T, class A = std::allocator<T> >
+#else
+template <class T, class A>
+#endif
+class stable_vector
+{
+ ///@cond
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename container_detail::
+ move_const_ref_type<T>::type insert_const_ref_type;
+ typedef typename boost::intrusive::pointer_traits
+ <typename allocator_traits_type::pointer>::
+ template rebind_pointer<void>::type void_ptr;
+ typedef typename boost::intrusive::pointer_traits
+ <void_ptr>::template
+ rebind_pointer<const void>::type const_void_ptr;
+ typedef typename boost::intrusive::pointer_traits
+ <void_ptr>::template
+ rebind_pointer<void_ptr>::type void_ptr_ptr;
+ typedef typename boost::intrusive::pointer_traits
+ <void_ptr>::template
+ rebind_pointer<const void_ptr>::type const_void_ptr_ptr;
+ typedef stable_vector_detail::node_type
+ <void_ptr, T> node_type_t;
+ typedef typename boost::intrusive::pointer_traits
+ <void_ptr>::template
+ rebind_pointer<node_type_t>::type node_type_ptr_t;
+ typedef stable_vector_detail::node_type_base
+ <void_ptr> node_type_base_t;
+ typedef typename boost::intrusive::pointer_traits
+ <void_ptr>::template
+ rebind_pointer<node_type_base_t>::type node_type_base_ptr_t;
+ typedef ::boost::container::vector<void_ptr,
+ typename allocator_traits_type::
+ template portable_rebind_alloc
+ <void_ptr>::type> impl_type;
+ typedef typename impl_type::iterator impl_iterator;
+ typedef typename impl_type::const_iterator const_impl_iterator;
+
+ typedef ::boost::container::container_detail::
+ integral_constant<unsigned, 1> allocator_v1;
+ typedef ::boost::container::container_detail::
+ integral_constant<unsigned, 2> allocator_v2;
+ typedef ::boost::container::container_detail::integral_constant
+ <unsigned, boost::container::container_detail::
+ version<A>::value> alloc_version;
+ typedef typename allocator_traits_type::
+ template portable_rebind_alloc
+ <node_type_t>::type node_allocator_type;
+
+ node_type_ptr_t allocate_one()
+ { return this->allocate_one(alloc_version()); }
+
+ template<class AllocatorVersion>
+ node_type_ptr_t allocate_one(AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { return node_alloc().allocate(1); }
+
+ template<class AllocatorVersion>
+ node_type_ptr_t allocate_one(AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { return node_alloc().allocate_one(); }
+
+ void deallocate_one(node_type_ptr_t p)
+ { return this->deallocate_one(p, alloc_version()); }
+
+ template<class AllocatorVersion>
+ void deallocate_one(node_type_ptr_t p, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { node_alloc().deallocate(p, 1); }
+
+ template<class AllocatorVersion>
+ void deallocate_one(node_type_ptr_t p, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ { node_alloc().deallocate_one(p); }
+
+ friend class stable_vector_detail::clear_on_destroy<stable_vector>;
+ ///@endcond
+ public:
+
+
+ // types:
+
+ typedef typename allocator_traits_type::reference reference;
+ typedef typename allocator_traits_type::const_reference const_reference;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef typename allocator_traits_type::const_pointer const_pointer;
+ typedef stable_vector_detail::iterator
+ <T,T&, pointer> iterator;
+ typedef stable_vector_detail::iterator
+ <T,const T&, const_pointer> const_iterator;
+ typedef typename impl_type::size_type size_type;
+ typedef typename iterator::difference_type difference_type;
+ typedef T value_type;
+ typedef A allocator_type;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef node_allocator_type stored_allocator_type;
+
+ ///@cond
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(stable_vector)
+ static const size_type ExtraPointers = 3;
+ //This container stores metadata at the end of the void_ptr vector with additional 3 pointers:
+ // back() is impl.back() - ExtraPointers;
+ // end node index is impl.end()[-3]
+ // Node cache first is impl.end()[-2];
+ // Node cache last is *impl.back();
+
+ typedef typename stable_vector_detail::
+ select_multiallocation_chain
+ < node_allocator_type
+ , alloc_version::value
+ >::type multiallocation_chain;
+ ///@endcond
+ public:
+
+ //! <b>Effects</b>: Default constructs a stable_vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ stable_vector()
+ : internal_data(), impl()
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit stable_vector(const A& al)
+ : internal_data(al),impl(al)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts n default contructed values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit stable_vector(size_type n)
+ : internal_data(A()),impl(A())
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->resize(n);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ stable_vector(size_type n, const T& t, const A& al=A())
+ : internal_data(al),impl(al)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cbegin(), n, t);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the stable_vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
+ //! throws or T's constructor taking an dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InputIterator>
+ stable_vector(InputIterator first,InputIterator last,const A& al=A())
+ : internal_data(al),impl(al)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cbegin(), first, last);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Copy constructs a stable_vector.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ stable_vector(const stable_vector& x)
+ : internal_data(allocator_traits<node_allocator_type>::
+ select_on_container_copy_construction(x.node_alloc()))
+ , impl(allocator_traits<allocator_type>::
+ select_on_container_copy_construction(x.impl.get_stored_allocator()))
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cbegin(), x.begin(), x.end());
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ stable_vector(BOOST_RV_REF(stable_vector) x)
+ : internal_data(boost::move(x.node_alloc())), impl(boost::move(x.impl))
+ {
+ this->priv_swap_members(x);
+ }
+
+ //! <b>Effects</b>: Destroys the stable_vector. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~stable_vector()
+ {
+ this->clear();
+ clear_pool();
+ }
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if (&x != this){
+ node_allocator_type &this_alloc = this->node_alloc();
+ const node_allocator_type &x_alloc = x.node_alloc();
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ container_detail::assign_alloc(this->node_alloc(), x.node_alloc(), flag);
+ container_detail::assign_alloc(this->impl.get_stored_allocator(), x.impl.get_stored_allocator(), flag);
+ this->assign(x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear.
+ stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
+ {
+ if (&x != this){
+ node_allocator_type &this_alloc = this->node_alloc();
+ node_allocator_type &x_alloc = x.node_alloc();
+ //If allocators are equal we can just swap pointers
+ if(this_alloc == x_alloc){
+ //Destroy objects but retain memory
+ this->clear();
+ this->impl = boost::move(x.impl);
+ this->priv_swap_members(x);
+ //Move allocator if needed
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_move_assignment::value> flag;
+ container_detail::move_alloc(this->node_alloc(), x.node_alloc(), flag);
+ }
+ //If unequal allocators, then do a one by one move
+ else{
+ typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template<typename InputIterator>
+ void assign(InputIterator first,InputIterator last)
+ {
+ assign_dispatch(first, last, boost::is_integral<InputIterator>());
+ }
+
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(size_type n,const T& t)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
+ }
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator()const {return node_alloc();}
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return node_alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+ { return node_alloc(); }
+
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator begin()
+ { return (impl.empty()) ? end(): iterator(node_ptr_cast(impl.front())) ; }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator begin()const
+ { return (impl.empty()) ? cend() : const_iterator(node_ptr_cast(impl.front())) ; }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() {return iterator(get_end_node());}
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end()const {return const_iterator(get_end_node());}
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() {return reverse_iterator(this->end());}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin()const {return const_reverse_iterator(this->end());}
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() {return reverse_iterator(this->begin());}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rend()const {return const_reverse_iterator(this->begin());}
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin()const {return this->begin();}
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend()const {return this->end();}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin()const{return this->rbegin();}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend()const {return this->rend();}
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type size() const
+ { return impl.empty() ? 0 : (impl.size() - ExtraPointers); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type max_size() const
+ { return impl.max_size() - ExtraPointers; }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type capacity() const
+ {
+ if(!impl.capacity()){
+ return 0;
+ }
+ else{
+ const size_type num_nodes = this->impl.size() + this->internal_data.pool_size;
+ const size_type num_buck = this->impl.capacity();
+ return (num_nodes < num_buck) ? num_nodes : num_buck;
+ }
+ }
+
+ //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const
+ { return impl.empty() || impl.size() == ExtraPointers; }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n, const T& t)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > size())
+ this->insert(this->cend(), n - this->size(), t);
+ else if(n < this->size())
+ this->erase(this->cbegin() + n, this->cend());
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are default constructed.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n)
+ {
+ typedef default_construct_iterator<value_type, difference_type> default_iterator;
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > size())
+ this->insert(this->cend(), default_iterator(n - this->size()), default_iterator());
+ else if(n < this->size())
+ this->erase(this->cbegin() + n, this->cend());
+ }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws.
+ void reserve(size_type n)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > this->max_size())
+ throw std::bad_alloc();
+
+ size_type size = this->size();
+ size_type old_capacity = this->capacity();
+ if(n > old_capacity){
+ this->initialize_end_node(n);
+ const void * old_ptr = &impl[0];
+ impl.reserve(n + ExtraPointers);
+ bool realloced = &impl[0] != old_ptr;
+ //Fix the pointers for the newly allocated buffer
+ if(realloced){
+ this->align_nodes(impl.begin(), impl.begin()+size+1);
+ }
+ //Now fill pool if data is not enough
+ if((n - size) > this->internal_data.pool_size){
+ this->add_to_pool((n - size) - this->internal_data.pool_size);
+ }
+ }
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n){return value(impl[n]);}
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n)const{return value(impl[n]);}
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
+ {
+ if(n>=size())
+ throw std::out_of_range("invalid subscript at stable_vector::at");
+ return operator[](n);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n)const
+ {
+ if(n>=size())
+ throw std::out_of_range("invalid subscript at stable_vector::at");
+ return operator[](n);
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front()
+ { return value(impl.front()); }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front()const
+ { return value(impl.front()); }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back()
+ { return value(*(&impl.back() - ExtraPointers)); }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back()const
+ { return value(*(&impl.back() - ExtraPointers)); }
+
+ //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(insert_const_ref_type x)
+ { return priv_push_back(x); }
+
+ #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ void push_back(T &x) { push_back(const_cast<const T &>(x)); }
+
+ template<class U>
+ void push_back(const U &u, typename container_detail::enable_if_c
+ <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
+ { return priv_push_back(u); }
+ #endif
+
+ //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
+ //! and moves the resources of mx to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(BOOST_RV_REF(T) t)
+ { this->insert(end(), boost::move(t)); }
+
+ //! <b>Effects</b>: Removes the last element from the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_back()
+ { this->erase(this->end()-1); }
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before position.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator position, insert_const_ref_type x)
+ { return this->priv_insert(position, x); }
+
+ #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast<const T &>(x)); }
+
+ template<class U>
+ iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c
+ <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
+ { return this->priv_insert(position, u); }
+ #endif
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before position with mx's resources.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator position, BOOST_RV_REF(T) x)
+ {
+ typedef repeat_iterator<T, difference_type> repeat_it;
+ typedef boost::move_iterator<repeat_it> repeat_move_it;
+ //Just call more general insert(pos, size, value) and return iterator
+ size_type pos_n = position - cbegin();
+ this->insert(position
+ ,repeat_move_it(repeat_it(x, 1))
+ ,repeat_move_it(repeat_it()));
+ return iterator(this->begin() + pos_n);
+ }
+
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert n copies of x before pos.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void insert(const_iterator position, size_type n, const T& t)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ this->insert_not_iter(position, n, t);
+ }
+
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to std::distance [first, last).
+ template <class InputIterator>
+ void insert(const_iterator position,InputIterator first, InputIterator last)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ this->insert_iter(position,first,last,
+ boost::mpl::not_<boost::is_integral<InputIterator> >());
+ }
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template<class ...Args>
+ void emplace_back(Args &&...args)
+ {
+ typedef emplace_functor<Args...> EmplaceFunctor;
+ typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
+ EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
+ this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
+ }
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before position
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ template<class ...Args>
+ iterator emplace(const_iterator position, Args && ...args)
+ {
+ //Just call more general insert(pos, size, value) and return iterator
+ size_type pos_n = position - cbegin();
+ typedef emplace_functor<Args...> EmplaceFunctor;
+ typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator;
+ EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
+ this->insert(position, EmplaceIterator(ef), EmplaceIterator());
+ return iterator(this->begin() + pos_n);
+ }
+
+ #else
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
+ BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
+ EmplaceFunctor; \
+ typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator; \
+ EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
+ BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
+ BOOST_PP_RPAREN_IF(n); \
+ this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator()); \
+ } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(const_iterator pos \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
+ BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \
+ EmplaceFunctor; \
+ typedef emplace_iterator<node_type_t, EmplaceFunctor, difference_type> EmplaceIterator; \
+ EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
+ BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
+ BOOST_PP_RPAREN_IF(n); \
+ size_type pos_n = pos - this->cbegin(); \
+ this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
+ return iterator(this->begin() + pos_n); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ //! <b>Effects</b>: Erases the element at position pos.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the elements between pos and the
+ //! last element. Constant if pos is the last element.
+ iterator erase(const_iterator position)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ difference_type d = position - this->cbegin();
+ impl_iterator it = impl.begin() + d;
+ this->delete_node(*it);
+ it = impl.erase(it);
+ this->align_nodes(it, get_last_align());
+ return this->begin()+d;
+ }
+
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and last
+ //! plus linear to the elements between pos and the last element.
+ iterator erase(const_iterator first, const_iterator last)
+ { return priv_erase(first, last, alloc_version()); }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(stable_vector & x)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
+ //vector's allocator is swapped here
+ this->impl.swap(x.impl);
+ this->priv_swap_members(x);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
+ void clear()
+ { this->erase(this->cbegin(),this->cend()); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ //! with previous allocations. The size of the stable_vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ void shrink_to_fit()
+ {
+ if(this->capacity()){
+ //First empty allocated node pool
+ this->clear_pool();
+ //If empty completely destroy the index, let's recover default-constructed state
+ if(this->empty()){
+ this->impl.clear();
+ this->impl.shrink_to_fit();
+ this->internal_data.set_end_pointer_to_default_constructed();
+ }
+ //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
+ else{
+ const size_type size = this->size();
+ const void* old_ptr = &impl[0];
+ this->impl.shrink_to_fit();
+ bool realloced = &impl[0] != old_ptr;
+ //Fix the pointers for the newly allocated buffer
+ if(realloced){
+ this->align_nodes(impl.begin(), impl.begin()+size+1);
+ }
+ }
+ }
+ }
+
+ /// @cond
+
+ iterator priv_insert(const_iterator position, const value_type &t)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert_iter(position, cvalue_iterator(t, 1), cvalue_iterator(), std::forward_iterator_tag());
+ }
+
+ void priv_push_back(const value_type &t)
+ { this->insert(end(), t); }
+
+ template<class AllocatorVersion>
+ void clear_pool(AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ if(!impl.empty() && impl.back()){
+ void_ptr &pool_first_ref = impl.end()[-2];
+ void_ptr &pool_last_ref = impl.back();
+
+ multiallocation_chain holder;
+ holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, this->internal_data.pool_size);
+ while(!holder.empty()){
+ node_type_ptr_t n = holder.front();
+ holder.pop_front();
+ this->deallocate_one(n);
+ }
+ pool_first_ref = pool_last_ref = 0;
+ this->internal_data.pool_size = 0;
+ }
+ }
+
+ template<class AllocatorVersion>
+ void clear_pool(AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ if(!impl.empty() && impl.back()){
+ void_ptr &pool_first_ref = impl.end()[-2];
+ void_ptr &pool_last_ref = impl.back();
+ multiallocation_chain holder;
+ holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
+ node_alloc().deallocate_individual(boost::move(holder));
+ pool_first_ref = pool_last_ref = 0;
+ this->internal_data.pool_size = 0;
+ }
+ }
+
+ void clear_pool()
+ {
+ this->clear_pool(alloc_version());
+ }
+
+ void add_to_pool(size_type n)
+ {
+ this->add_to_pool(n, alloc_version());
+ }
+
+ template<class AllocatorVersion>
+ void add_to_pool(size_type n, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ size_type remaining = n;
+ while(remaining--){
+ this->put_in_pool(this->allocate_one());
+ }
+ }
+
+ template<class AllocatorVersion>
+ void add_to_pool(size_type n, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ void_ptr &pool_first_ref = impl.end()[-2];
+ void_ptr &pool_last_ref = impl.back();
+ multiallocation_chain holder;
+ holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
+ //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<multiallocation_chain>::value == true));
+ multiallocation_chain m (node_alloc().allocate_individual(n));
+ holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
+ this->internal_data.pool_size += n;
+ std::pair<void_ptr, void_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
+ }
+
+ void put_in_pool(node_type_ptr_t p)
+ {
+ void_ptr &pool_first_ref = impl.end()[-2];
+ void_ptr &pool_last_ref = impl.back();
+ multiallocation_chain holder;
+ holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
+ holder.push_front(p);
+ ++this->internal_data.pool_size;
+ std::pair<void_ptr, void_ptr> ret(holder.extract_data());
+ pool_first_ref = ret.first;
+ pool_last_ref = ret.second;
+ }
+
+ node_type_ptr_t get_from_pool()
+ {
+ if(!impl.back()){
+ return node_type_ptr_t(0);
+ }
+ else{
+ void_ptr &pool_first_ref = impl.end()[-2];
+ void_ptr &pool_last_ref = impl.back();
+ multiallocation_chain holder;
+ holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
+ node_type_ptr_t ret = holder.front();
+ holder.pop_front();
+ --this->internal_data.pool_size;
+ if(!internal_data.pool_size){
+ pool_first_ref = pool_last_ref = void_ptr(0);
+ }
+ else{
+ std::pair<void_ptr, void_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
+ }
+ return ret;
+ }
+ }
+
+ void insert_iter_prolog(size_type n, difference_type d)
+ {
+ initialize_end_node(n);
+ const void* old_ptr = &impl[0];
+ //size_type old_capacity = capacity();
+ //size_type old_size = size();
+ impl.insert(impl.begin()+d, n, 0);
+ bool realloced = &impl[0] != old_ptr;
+ //Fix the pointers for the newly allocated buffer
+ if(realloced){
+ align_nodes(impl.begin(), impl.begin()+d);
+ }
+ }
+
+ template<typename InputIterator>
+ void assign_dispatch(InputIterator first, InputIterator last, boost::mpl::false_)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ iterator first1 = this->begin();
+ iterator last1 = this->end();
+ for ( ; first1 != last1 && first != last; ++first1, ++first)
+ *first1 = *first;
+ if (first == last){
+ this->erase(first1, last1);
+ }
+ else{
+ this->insert(last1, first, last);
+ }
+ }
+
+ template<typename Integer>
+ void assign_dispatch(Integer n, Integer t, boost::mpl::true_)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ this->assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
+ }
+
+ iterator priv_erase(const_iterator first, const_iterator last, allocator_v1)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
+ if(d1 != d2){
+ impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2);
+ for(impl_iterator it = it1; it != it2; ++it)
+ this->delete_node(*it);
+ impl_iterator e = impl.erase(it1, it2);
+ this->align_nodes(e, get_last_align());
+ }
+ return iterator(this->begin() + d1);
+ }
+
+ impl_iterator get_last_align()
+ {
+ return impl.end() - (ExtraPointers - 1);
+ }
+
+ const_impl_iterator get_last_align() const
+ {
+ return impl.cend() - (ExtraPointers - 1);
+ }
+
+ template<class AllocatorVersion>
+ iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
+ typename boost::container::container_detail::enable_if_c
+ <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
+ ::value>::type * = 0)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ return priv_erase(first, last, allocator_v1());
+ }
+
+ static node_type_ptr_t node_ptr_cast(const void_ptr &p)
+ {
+ return node_type_ptr_t(static_cast<node_type_t*>(stable_vector_detail::to_raw_pointer(p)));
+ }
+
+ static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p)
+ {
+ return node_type_base_ptr_t(static_cast<node_type_base_t*>(stable_vector_detail::to_raw_pointer(p)));
+ }
+
+ static value_type& value(const void_ptr &p)
+ {
+ return node_ptr_cast(p)->value;
+ }
+
+ void initialize_end_node(size_type impl_capacity = 0)
+ {
+ if(impl.empty()){
+ impl.reserve(impl_capacity + ExtraPointers);
+ impl.resize (ExtraPointers, void_ptr(0));
+ impl[0] = &this->internal_data.end_node;
+ this->internal_data.end_node.up = &impl[0];
+ }
+ }
+
+ void readjust_end_node()
+ {
+ if(!this->impl.empty()){
+ void_ptr &end_node_ref = *(this->get_last_align()-1);
+ end_node_ref = this->get_end_node();
+ this->internal_data.end_node.up = &end_node_ref;
+ }
+ else{
+ this->internal_data.end_node.up = void_ptr(&this->internal_data.end_node.up);
+ }
+ }
+
+ node_type_ptr_t get_end_node() const
+ {
+ const node_type_base_t* cp = &this->internal_data.end_node;
+ node_type_base_t* p = const_cast<node_type_base_t*>(cp);
+ return node_ptr_cast(p);
+ }
+
+ template<class Iter>
+ void_ptr new_node(const void_ptr &up, Iter it)
+ {
+ node_type_ptr_t p = this->allocate_one();
+ try{
+ boost::container::construct_in_place(this->node_alloc(), &*p, it);
+ p->set_pointer(up);
+ }
+ catch(...){
+ this->deallocate_one(p);
+ throw;
+ }
+ return p;
+ }
+
+ void delete_node(const void_ptr &p)
+ {
+ node_type_ptr_t n(node_ptr_cast(p));
+ allocator_traits<node_allocator_type>::
+ destroy(this->node_alloc(), container_detail::to_raw_pointer(n));
+ this->put_in_pool(n);
+ }
+
+ static void align_nodes(impl_iterator first, impl_iterator last)
+ {
+ while(first!=last){
+ node_ptr_cast(*first)->up = void_ptr(&*first);
+ ++first;
+ }
+ }
+
+ void insert_not_iter(const_iterator position, size_type n, const T& t)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ this->insert_iter(position, cvalue_iterator(t, n), cvalue_iterator(), std::forward_iterator_tag());
+ }
+
+ template <class InputIterator>
+ void insert_iter(const_iterator position,InputIterator first,InputIterator last, boost::mpl::true_)
+ {
+ typedef typename std::iterator_traits<InputIterator>::iterator_category category;
+ this->insert_iter(position, first, last, category());
+ }
+
+ template <class InputIterator>
+ void insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag)
+ {
+ for(; first!=last; ++first){
+ this->insert(position, *first);
+ }
+ }
+
+ template <class InputIterator>
+ iterator insert_iter(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
+ {
+ size_type n = (size_type)std::distance(first,last);
+ difference_type d = position-this->cbegin();
+ if(n){
+ this->insert_iter_prolog(n, d);
+ const impl_iterator it(impl.begin() + d);
+ this->insert_iter_fwd(it, first, last, n);
+ //Fix the pointers for the newly allocated buffer
+ this->align_nodes(it + n, get_last_align());
+ }
+ return this->begin() + d;
+ }
+
+ template <class FwdIterator>
+ void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
+ {
+ size_type i=0;
+ try{
+ while(first!=last){
+ it[i] = this->new_node(void_ptr_ptr(&it[i]), first);
+ ++first;
+ ++i;
+ }
+ }
+ catch(...){
+ impl_iterator e = impl.erase(it + i, it + n);
+ this->align_nodes(e, get_last_align());
+ throw;
+ }
+ }
+
+ template <class FwdIterator>
+ void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
+ {
+ multiallocation_chain mem(node_alloc().allocate_individual(n));
+
+ size_type i = 0;
+ node_type_ptr_t p = 0;
+ try{
+ while(first != last){
+ p = mem.front();
+ mem.pop_front();
+ //This can throw
+ boost::container::construct_in_place(this->node_alloc(), &*p, first);
+ p->set_pointer(void_ptr_ptr(&it[i]));
+ ++first;
+ it[i] = p;
+ ++i;
+ }
+ }
+ catch(...){
+ node_alloc().deallocate_one(p);
+ node_alloc().deallocate_many(boost::move(mem));
+ impl_iterator e = impl.erase(it+i, it+n);
+ this->align_nodes(e, get_last_align());
+ throw;
+ }
+ }
+
+ template <class FwdIterator>
+ void insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
+ {
+ size_type i = 0;
+ node_type_ptr_t p = 0;
+ try{
+ while(first != last){
+ p = this->get_from_pool();
+ if(!p){
+ insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
+ break;
+ }
+ //This can throw
+ boost::container::construct_in_place(this->node_alloc(), &*p, first);
+ p->set_pointer(void_ptr_ptr(&it[i]));
+ ++first;
+ it[i]=p;
+ ++i;
+ }
+ }
+ catch(...){
+ put_in_pool(p);
+ impl_iterator e = impl.erase(it+i, it+n);
+ this->align_nodes(e, get_last_align());
+ throw;
+ }
+ }
+
+ template <class InputIterator>
+ void insert_iter(const_iterator position, InputIterator first, InputIterator last, boost::mpl::false_)
+ {
+ this->insert_not_iter(position, first, last);
+ }
+
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ bool invariant()const
+ {
+ if(impl.empty())
+ return !capacity() && !size();
+ if(get_end_node() != *(impl.end() - ExtraPointers)){
+ return false;
+ }
+ for(const_impl_iterator it = impl.begin(), it_end = get_last_align(); it != it_end; ++it){
+ if(const_void_ptr(node_ptr_cast(*it)->up) !=
+ const_void_ptr(const_void_ptr_ptr(&*it)))
+ return false;
+ }
+ size_type n = capacity()-size();
+ const void_ptr &pool_head = impl.back();
+ size_type num_pool = 0;
+ node_type_ptr_t p = node_ptr_cast(pool_head);
+ while(p){
+ ++num_pool;
+ p = node_ptr_cast(p->up);
+ }
+ return n >= num_pool;
+ }
+
+ class invariant_checker
+ {
+ invariant_checker(const invariant_checker &);
+ invariant_checker & operator=(const invariant_checker &);
+ const stable_vector* p;
+
+ public:
+ invariant_checker(const stable_vector& v):p(&v){}
+ ~invariant_checker(){BOOST_ASSERT(p->invariant());}
+ void touch(){}
+ };
+ #endif
+
+ class ebo_holder
+ : public node_allocator_type
+ {
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
+ public:
+/*
+ explicit ebo_holder(BOOST_RV_REF(ebo_holder) x)
+ : node_allocator_type(boost::move(static_cast<node_allocator_type&>(x)))
+ , pool_size(0)
+ , end_node()
+ {}
+*/
+ template<class AllocatorRLValue>
+ explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
+ : node_allocator_type(boost::forward<AllocatorRLValue>(a))
+ , pool_size(0)
+ , end_node()
+ {
+ this->set_end_pointer_to_default_constructed();
+ }
+
+ ebo_holder()
+ : node_allocator_type()
+ , pool_size(0)
+ , end_node()
+ {
+ this->set_end_pointer_to_default_constructed();
+ }
+
+ void set_end_pointer_to_default_constructed()
+ {
+ end_node.set_pointer(void_ptr(&end_node.up));
+ }
+
+ size_type pool_size;
+ node_type_base_t end_node;
+ } internal_data;
+
+ void priv_swap_members(stable_vector &x)
+ {
+ container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
+ this->readjust_end_node();
+ x.readjust_end_node();
+ }
+
+ node_allocator_type &node_alloc() { return internal_data; }
+ const node_allocator_type &node_alloc() const { return internal_data; }
+
+ impl_type impl;
+ /// @endcond
+};
+
+template <typename T,typename A>
+bool operator==(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
+}
+
+template <typename T,typename A>
+bool operator< (const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
+}
+
+template <typename T,typename A>
+bool operator!=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return !(x==y);
+}
+
+template <typename T,typename A>
+bool operator> (const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return y<x;
+}
+
+template <typename T,typename A>
+bool operator>=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return !(x<y);
+}
+
+template <typename T,typename A>
+bool operator<=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
+{
+ return !(x>y);
+}
+
+// specialized algorithms:
+
+template <typename T, typename A>
+void swap(stable_vector<T,A>& x,stable_vector<T,A>& y)
+{
+ x.swap(y);
+}
+
+/// @cond
+
+#undef STABLE_VECTOR_CHECK_INVARIANT
+
+/// @endcond
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_STABLE_VECTOR_HPP