]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/container/vector.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / container / vector.hpp
index 89ed12e99f9aac9da0f11d650e99b2a69b96d4f9..099a8781c24d5ab20db718432912be1d8ba01fd1 100644 (file)
@@ -97,6 +97,16 @@ class vec_iterator
    private:
    Pointer m_ptr;
 
+   class nat
+   {
+      public:
+      Pointer get_ptr() const
+      { return Pointer();  }
+   };
+   typedef typename dtl::if_c< IsConst
+                             , vec_iterator<Pointer, false>
+                             , nat>::type                                           nonconst_iterator;
+
    public:
    BOOST_CONTAINER_FORCEINLINE const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
    {  return   m_ptr;  }
@@ -116,48 +126,55 @@ class vec_iterator
       : m_ptr()   //Value initialization to achieve "null iterators" (N3644)
    {}
 
-   BOOST_CONTAINER_FORCEINLINE vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+   BOOST_CONTAINER_FORCEINLINE vec_iterator(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
+      :  m_ptr(other.get_ptr())
+   {}
+
+   BOOST_CONTAINER_FORCEINLINE vec_iterator(const nonconst_iterator &other) BOOST_NOEXCEPT_OR_NOTHROW
       :  m_ptr(other.get_ptr())
    {}
 
+   BOOST_CONTAINER_FORCEINLINE vec_iterator & operator=(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
+   {  m_ptr = other.get_ptr();   return *this;  }
+
    //Pointer like operators
    BOOST_CONTAINER_FORCEINLINE reference operator*()   const BOOST_NOEXCEPT_OR_NOTHROW
-   {  return *m_ptr;  }
+   {  BOOST_ASSERT(!!m_ptr);  return *m_ptr;  }
 
    BOOST_CONTAINER_FORCEINLINE pointer operator->()  const BOOST_NOEXCEPT_OR_NOTHROW
-   {  return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*());  }
+   {  return m_ptr;  }
 
    BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
-   {  return m_ptr[off];   }
+   {  BOOST_ASSERT(!!m_ptr);  return m_ptr[off];  }
 
    //Increment / Decrement
    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
-   { ++m_ptr;  return *this; }
+   {  BOOST_ASSERT(!!m_ptr); ++m_ptr;  return *this; }
 
    BOOST_CONTAINER_FORCEINLINE vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
-   {  return vec_iterator(m_ptr++); }
+   {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr++); }
 
    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
-   {  --m_ptr; return *this;  }
+   {  BOOST_ASSERT(!!m_ptr); --m_ptr; return *this;  }
 
    BOOST_CONTAINER_FORCEINLINE vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
-   {  return vec_iterator(m_ptr--); }
+   {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr--); }
 
    //Arithmetic
    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
-   {  m_ptr += off; return *this;   }
+   {  BOOST_ASSERT(m_ptr || !off); m_ptr += off; return *this;   }
 
    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
-   {  m_ptr -= off; return *this;   }
+   {  BOOST_ASSERT(m_ptr || !off); m_ptr -= off; return *this;   }
 
    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
-   {  return vec_iterator(x.m_ptr+off);  }
+   {  BOOST_ASSERT(x.m_ptr || !off); return vec_iterator(x.m_ptr+off);  }
 
    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
-   {  right.m_ptr += off;  return right; }
+   {  BOOST_ASSERT(right.m_ptr || !off); right.m_ptr += off;  return right; }
 
    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
-   {  left.m_ptr -= off;  return left; }
+   {  BOOST_ASSERT(left.m_ptr || !off); left.m_ptr -= off;  return left; }
 
    BOOST_CONTAINER_FORCEINLINE friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
    {  return left.m_ptr - right.m_ptr;   }
@@ -236,7 +253,6 @@ struct vector_value_traits_base
    static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
 };
 
-
 template <class Allocator>
 struct vector_value_traits
    : public vector_value_traits_base<typename Allocator::value_type>
@@ -265,12 +281,12 @@ struct vector_alloc_holder
    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
 
    public:
-   typedef Allocator                                     allocator_type;
-   typedef StoredSizeType                                stored_size_type;
-   typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
-   typedef typename allocator_traits_type::pointer       pointer;
-   typedef typename allocator_traits_type::size_type     size_type;
-   typedef typename allocator_traits_type::value_type    value_type;
+   typedef Allocator                                           allocator_type;
+   typedef StoredSizeType                                      stored_size_type;
+   typedef boost::container::allocator_traits<allocator_type>  allocator_traits_type;
+   typedef typename allocator_traits_type::pointer             pointer;
+   typedef typename allocator_traits_type::size_type           size_type;
+   typedef typename allocator_traits_type::value_type          value_type;
 
    static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
    {
@@ -290,20 +306,20 @@ struct vector_alloc_holder
 
    //Constructor, does not throw
    vector_alloc_holder()
-      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
-      : Allocator(), m_start(), m_size(), m_capacity()
+      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
+      : allocator_type(), m_start(), m_size(), m_capacity()
    {}
 
    //Constructor, does not throw
    template<class AllocConvertible>
    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
-      : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
+      : allocator_type(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
    {}
 
    //Constructor, does not throw
    template<class AllocConvertible>
    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
-      : Allocator(boost::forward<AllocConvertible>(a))
+      : allocator_type(boost::forward<AllocConvertible>(a))
       , m_start()
       //Size is initialized here so vector should only call uninitialized_xxx after this
       , m_size(static_cast<stored_size_type>(initial_size))
@@ -319,7 +335,7 @@ struct vector_alloc_holder
 
    //Constructor, does not throw
    vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
-      : Allocator()
+      : allocator_type()
       , m_start()
       //Size is initialized here so vector should only call uninitialized_xxx after this
       , m_size(static_cast<stored_size_type>(initial_size))
@@ -334,7 +350,7 @@ struct vector_alloc_holder
    }
 
    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
-      : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+      : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
       , m_start(holder.m_start)
       , m_size(holder.m_size)
       , m_capacity(holder.m_capacity)
@@ -344,7 +360,7 @@ struct vector_alloc_holder
    }
 
    vector_alloc_holder(initial_capacity_t, pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
-      : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+      : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
       , m_start(p)
       , m_size(holder.m_size)
       , m_capacity(static_cast<stored_size_type>(capacity))
@@ -373,8 +389,8 @@ struct vector_alloc_holder
    }
 
    vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
-      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
-      : Allocator()
+      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
+      : allocator_type()
       , m_start(p)
       , m_size()
       //n is guaranteed to fit into stored_size_type
@@ -383,7 +399,7 @@ struct vector_alloc_holder
 
    template<class AllocFwd>
    vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
-      : Allocator(::boost::forward<AllocFwd>(a))
+      : allocator_type(::boost::forward<AllocFwd>(a))
       , m_start(p)
       , m_size()
       , m_capacity(n)
@@ -399,7 +415,7 @@ struct vector_alloc_holder
    BOOST_CONTAINER_FORCEINLINE pointer allocation_command(boost::container::allocation_type command,
                               size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
    {
-      typedef typename dtl::version<Allocator>::type alloc_version;
+      typedef typename dtl::version<allocator_type>::type alloc_version;
       return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
    }
 
@@ -470,10 +486,10 @@ struct vector_alloc_holder
       x.m_size = x.m_capacity = 0;
    }
 
-   BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+   BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
    {  return *this;  }
 
-   BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+   BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
    {  return *this;  }
 
    BOOST_CONTAINER_FORCEINLINE const pointer   &start() const     BOOST_NOEXCEPT_OR_NOTHROW
@@ -485,6 +501,9 @@ struct vector_alloc_holder
    BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c)  BOOST_NOEXCEPT_OR_NOTHROW
       {  BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c;  }
 
+   static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
+   { }
+
    private:
    void priv_first_allocation(size_type cap)
    {
@@ -553,31 +572,33 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
 
    public:
-   typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+   typedef Allocator                                     allocator_type;
+   typedef boost::container::
+      allocator_traits<allocator_type>                   allocator_traits_type;
    typedef typename allocator_traits_type::pointer       pointer;
    typedef typename allocator_traits_type::size_type     size_type;
    typedef typename allocator_traits_type::value_type    value_type;
    typedef StoredSizeType                                stored_size_type;
-
+      
    template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
    friend struct vector_alloc_holder;
 
    //Constructor, does not throw
    vector_alloc_holder()
-      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
-      : Allocator(), m_size()
+      BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
+      : allocator_type(), m_size()
    {}
 
    //Constructor, does not throw
    template<class AllocConvertible>
    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
-      : Allocator(boost::forward<AllocConvertible>(a)), m_size()
+      : allocator_type(boost::forward<AllocConvertible>(a)), m_size()
    {}
 
    //Constructor, does not throw
    template<class AllocConvertible>
    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
-      : Allocator(boost::forward<AllocConvertible>(a))
+      : allocator_type(boost::forward<AllocConvertible>(a))
       , m_size(initial_size)  //Size is initialized here...
    {
       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
@@ -586,7 +607,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
 
    //Constructor, does not throw
    vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
-      : Allocator()
+      : allocator_type()
       , m_size(initial_size)  //Size is initialized here...
    {
       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
@@ -594,7 +615,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
    }
 
    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
-      : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+      : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
       , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
    {
       ::boost::container::uninitialized_move_alloc_n
@@ -603,7 +624,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
 
    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
    vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
-      : Allocator()
+      : allocator_type()
       , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
    {
       //Different allocator type so we must check we have enough storage
@@ -613,10 +634,13 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
    }
 
+   static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
+   {  allocator_type::on_capacity_overflow();  }
+
    BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
    {
-      if(cap > Allocator::internal_capacity){
-         throw_bad_alloc();
+      if(cap > allocator_type::internal_capacity){
+         on_capacity_overflow();
       }
    }
 
@@ -628,34 +652,39 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
    void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
    {
-      if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
-         throw_bad_alloc();
+      typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
+      if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
+         on_capacity_overflow();
       }
       this->priv_deep_swap(x);
    }
 
    BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
    {  //Containers with version 0 allocators can't be moved without moving elements one by one
-      throw_bad_alloc();
+      on_capacity_overflow();
    }
 
 
    BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
    {  //Containers with version 0 allocators can't be moved without moving elements one by one
-      throw_bad_alloc();
+      on_capacity_overflow();
    }
 
-   BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+   BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
    {  return *this;  }
 
-   BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+   BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
    {  return *this;  }
 
    BOOST_CONTAINER_FORCEINLINE bool try_expand_fwd(size_type at_least)
    {  return !at_least;  }
 
-   BOOST_CONTAINER_FORCEINLINE pointer start() const       BOOST_NOEXCEPT_OR_NOTHROW {  return Allocator::internal_storage();  }
-   BOOST_CONTAINER_FORCEINLINE size_type  capacity() const BOOST_NOEXCEPT_OR_NOTHROW {  return Allocator::internal_capacity;  }
+   BOOST_CONTAINER_FORCEINLINE pointer start() const       BOOST_NOEXCEPT_OR_NOTHROW
+   {  return allocator_type::internal_storage();  }
+   
+   BOOST_CONTAINER_FORCEINLINE size_type  capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+   {  return allocator_type::internal_capacity;  }
+   
    stored_size_type m_size;
 
    private:
@@ -663,7 +692,7 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
    void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
    {
-      const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
+      const size_type MaxTmpStorage = sizeof(value_type)*allocator_type::internal_capacity;
       value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
       value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
 
@@ -679,18 +708,6 @@ struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
 
 struct growth_factor_60;
 
-template<class T, class Default>
-struct default_if_void
-{
-   typedef T type;
-};
-
-template<class Default>
-struct default_if_void<void, Default>
-{
-   typedef Default type;
-};
-
 template<class Options, class AllocatorSizeType>
 struct get_vector_opt
 {
@@ -705,7 +722,6 @@ struct get_vector_opt<void, AllocatorSizeType>
    typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
 };
 
-
 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
 
 //! A vector is a sequence that supports random access to elements, constant
@@ -714,14 +730,39 @@ struct get_vector_opt<void, AllocatorSizeType>
 //! elements in a vector may vary dynamically; memory management is automatic.
 //!
 //! \tparam T The type of object that is stored in the vector
-//! \tparam Allocator The allocator used for all internal memory management
+//! \tparam A The allocator used for all internal memory management, use void
+//!   for the default allocator
 //! \tparam Options A type produced from \c boost::container::vector_options.
-template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>), class Options BOOST_CONTAINER_DOCONLY(= void) >
+template <class T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
 class vector
 {
-   #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+public:
+   //////////////////////////////////////////////
+   //
+   //                    types
+   //
+   //////////////////////////////////////////////
+   typedef T                                                               value_type;
+   typedef BOOST_CONTAINER_IMPDEF
+      (typename real_allocator<T BOOST_MOVE_I A>::type)            allocator_type;
+   typedef ::boost::container::allocator_traits<allocator_type>            allocator_traits_t;
+   typedef typename   allocator_traits<allocator_type>::pointer            pointer;
+   typedef typename   allocator_traits<allocator_type>::const_pointer      const_pointer;
+   typedef typename   allocator_traits<allocator_type>::reference          reference;
+   typedef typename   allocator_traits<allocator_type>::const_reference    const_reference;
+   typedef typename   allocator_traits<allocator_type>::size_type          size_type;
+   typedef typename   allocator_traits<allocator_type>::difference_type    difference_type;
+   typedef allocator_type                                                  stored_allocator_type;
+   typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I false>)       iterator;
+   typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I true >)       const_iterator;
+   typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
+   typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
+
+private:
 
-   typedef typename boost::container::allocator_traits<Allocator>::size_type  alloc_size_type;
+   #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+   typedef typename boost::container::
+      allocator_traits<allocator_type>::size_type                             alloc_size_type;
    typedef typename get_vector_opt<Options, alloc_size_type>::type            options_type;
    typedef typename options_type::growth_factor_type                          growth_factor_type;
    typedef typename options_type::stored_size_type                            stored_size_type;
@@ -731,51 +772,32 @@ class vector
    BOOST_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
                         dtl::is_same<stored_size_type, alloc_size_type>::value) );
 
-   typedef typename dtl::version<Allocator>::type alloc_version;
-   typedef boost::container::vector_alloc_holder<Allocator, stored_size_type> alloc_holder_t;
+   typedef typename dtl::version<allocator_type>::type alloc_version;
+   typedef boost::container::vector_alloc_holder
+      <allocator_type, stored_size_type> alloc_holder_t;
+
    alloc_holder_t m_holder;
-   typedef allocator_traits<Allocator>                      allocator_traits_type;
-   template <class U, class UAllocator, class UOptions>
+
+   typedef allocator_traits<allocator_type>                      allocator_traits_type;
+   template <class U, class UA, class UOptions>
    friend class vector;
 
-   typedef typename allocator_traits_type::pointer  pointer_impl;
-   typedef vec_iterator<pointer_impl, false> iterator_impl;
-   typedef vec_iterator<pointer_impl, true > const_iterator_impl;
 
    protected:
-   static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator)
+   BOOST_CONTAINER_FORCEINLINE
+      static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
    {  return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator);  }
 
-   static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p
-                                  , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator)
+   BOOST_CONTAINER_FORCEINLINE
+      static bool are_swap_propagable( const allocator_type &l_a, pointer l_p
+                                     , const allocator_type &r_a, pointer r_p, bool const propagate_allocator)
    {  return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator);  }
 
    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-   public:
-   //////////////////////////////////////////////
-   //
-   //                    types
-   //
-   //////////////////////////////////////////////
-
-   typedef T                                                                           value_type;
-   typedef typename ::boost::container::allocator_traits<Allocator>::pointer           pointer;
-   typedef typename ::boost::container::allocator_traits<Allocator>::const_pointer     const_pointer;
-   typedef typename ::boost::container::allocator_traits<Allocator>::reference         reference;
-   typedef typename ::boost::container::allocator_traits<Allocator>::const_reference   const_reference;
-   typedef typename ::boost::container::allocator_traits<Allocator>::size_type         size_type;
-   typedef typename ::boost::container::allocator_traits<Allocator>::difference_type   difference_type;
-   typedef Allocator                                                                   allocator_type;
-   typedef Allocator                                                                   stored_allocator_type;
-   typedef BOOST_CONTAINER_IMPDEF(iterator_impl)                                       iterator;
-   typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl)                                 const_iterator;
-   typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
-   typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
-
    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
    private:
    BOOST_COPYABLE_AND_MOVABLE(vector)
-   typedef vector_value_traits<Allocator> value_traits;
+   typedef vector_value_traits<allocator_type> value_traits;
    typedef constant_iterator<T, difference_type>            cvalue_iterator;
 
    protected:
@@ -806,7 +828,7 @@ class vector
    //! <b>Throws</b>: Nothing.
    //!
    //! <b>Complexity</b>: Constant.
-   vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+   vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
       : m_holder()
    {}
 
@@ -931,6 +953,12 @@ class vector
    //!   throws or T's constructor taking a dereferenced InIt throws.
    //!
    //! <b>Complexity</b>: Linear to the range [first, last).
+//    template <class InIt>
+//    vector(InIt first, InIt last
+//           BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+//                                  < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+//                                  BOOST_MOVE_I dtl::nat >::type * = 0)
+//           ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
    template <class InIt>
    vector(InIt first, InIt last
       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
@@ -947,6 +975,12 @@ class vector
    //!   throws or T's constructor taking a dereferenced InIt throws.
    //!
    //! <b>Complexity</b>: Linear to the range [first, last).
+//    template <class InIt>
+//    vector(InIt first, InIt last, const allocator_type& a
+//           BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+//                                  < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+//                                  BOOST_MOVE_I dtl::nat >::type * = 0)
+//           ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
    template <class InIt>
    vector(InIt first, InIt last, const allocator_type& a
       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
@@ -1009,10 +1043,10 @@ class vector
    //! <b>Complexity</b>: Linear.
    //!
    //! <b>Note</b>: Non-standard extension to support static_vector
-   template<class OtherAllocator>
-   vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+   template<class OtherA>
+   vector(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
          , typename dtl::enable_if_c
-            < dtl::is_version<OtherAllocator, 0>::value>::type * = 0
+            < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value>::type * = 0
          )
       :  m_holder(boost::move(x.m_holder))
    {}
@@ -1087,7 +1121,7 @@ class vector
    //! <b>Complexity</b>: Linear to the number of elements in x.
    BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
    {
-      if (&x != this){
+      if (BOOST_LIKELY(&x != this)){
          this->priv_copy_assign(x);
       }
       return *this;
@@ -1119,8 +1153,9 @@ class vector
       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
                         || allocator_traits_type::is_always_equal::value)
    {
-      BOOST_ASSERT(&x != this);
-      this->priv_move_assign(boost::move(x));
+      if (BOOST_LIKELY(&x != this)){
+         this->priv_move_assign(boost::move(x));
+      }
       return *this;
    }
 
@@ -1136,13 +1171,13 @@ class vector
    //! <b>Complexity</b>: Linear.
    //!
    //! <b>Note</b>: Non-standard extension to support static_vector
-   template<class OtherAllocator>
+   template<class OtherA>
    BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
                            < vector&
-                           , dtl::is_version<OtherAllocator, 0>
-                           , dtl::is_different<OtherAllocator, allocator_type>
+                           , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
+                           , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
                            >::type
-      operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x)
+      operator=(BOOST_RV_REF_BEG vector<value_type, OtherA, Options> BOOST_RV_REF_END x)
    {
       this->priv_move_assign(boost::move(x));
       return *this;
@@ -1158,13 +1193,13 @@ class vector
    //! <b>Complexity</b>: Linear.
    //!
    //! <b>Note</b>: Non-standard extension to support static_vector
-   template<class OtherAllocator>
+   template<class OtherA>
    BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
                            < vector&
-                           , dtl::is_version<OtherAllocator, 0>
-                           , dtl::is_different<OtherAllocator, allocator_type>
+                           , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
+                           , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
                            >::type
-      operator=(const vector<value_type, OtherAllocator> &x)
+      operator=(const vector<value_type, OtherA, Options> &x)
    {
       this->priv_copy_assign(x);
       return *this;
@@ -1180,6 +1215,7 @@ class vector
    //! <b>Complexity</b>: Linear to n.
    template <class InIt>
    void assign(InIt first, InIt last
+      //Input iterators or version 0 allocator
       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
          < void
          BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
@@ -1229,6 +1265,7 @@ class vector
    //! <b>Complexity</b>: Linear to n.
    template <class FwdIt>
    void assign(FwdIt first, FwdIt last
+      //Forward iterators and version > 0 allocator
       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
          < void
          BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
@@ -1268,21 +1305,9 @@ class vector
             //Forward expansion, use assignment + back deletion/construction that comes later
          }
       }
-      //Overwrite all elements we can from [first, last)
-      iterator cur = this->begin();
-      const iterator end_it = this->end();
-      for ( ; first != last && cur != end_it; ++cur, ++first){
-         *cur = *first;
-      }
 
-      if (first == last){
-         //There are no more elements in the sequence, erase remaining
-         this->priv_destroy_last_n(this->size() - input_sz);
-      }
-      else{
-         //Uninitialized construct at end the remaining range
-         this->priv_uninitialized_construct_at_end(first, last);
-      }
+      boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
+      this->m_holder.m_size = input_sz;
    }
 
    //! <b>Effects</b>: Assigns the n copies of val to *this.
@@ -1350,7 +1375,11 @@ class vector
    //!
    //! <b>Complexity</b>: Constant.
    BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
-   { return iterator(this->m_holder.start() + this->m_holder.m_size); }
+   {
+      pointer   const bg = this->m_holder.start();
+      size_type const sz = this->m_holder.m_size;
+      return iterator(BOOST_LIKELY(sz) ? bg + sz : bg);  //Avoid UB on null-pointer arithmetic
+   }
 
    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
    //!
@@ -1410,7 +1439,12 @@ class vector
    //!
    //! <b>Complexity</b>: Constant.
    BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
-   { return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
+   {
+      pointer   const bg = this->m_holder.start();
+      size_type const sz = this->m_holder.m_size;
+      return const_iterator(BOOST_LIKELY(sz) ? bg + sz : bg);  //Avoid UB on null-pointer arithmetic
+   }
+   //{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
 
    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
    //! of the reversed vector.
@@ -1755,7 +1789,7 @@ class vector
          return *p;
       }
       else{
-         typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type;
+         typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
          return *this->priv_forward_range_insert_no_capacity
             (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
       }
@@ -1796,7 +1830,7 @@ class vector
    {
       BOOST_ASSERT(this->priv_in_range_or_end(position));
       //Just call more general insert(pos, size, value) and return iterator
-      typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type;
+      typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
       return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
                                             , type(::boost::forward<Args>(args)...));
    }
@@ -1815,7 +1849,7 @@ class vector
          return *p;\
       }\
       else{\
-         typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+         typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
          return *this->priv_forward_range_insert_no_capacity\
             ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
       }\
@@ -1837,7 +1871,7 @@ class vector
    iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
    {\
       BOOST_ASSERT(this->priv_in_range_or_end(pos));\
-      typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+      typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
    }\
    //
@@ -1903,7 +1937,7 @@ class vector
    iterator insert(const_iterator p, size_type n, const T& x)
    {
       BOOST_ASSERT(this->priv_in_range_or_end(p));
-      dtl::insert_n_copies_proxy<Allocator, T*> proxy(x);
+      dtl::insert_n_copies_proxy<allocator_type, T*> proxy(x);
       return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
    }
 
@@ -1949,7 +1983,7 @@ class vector
       )
    {
       BOOST_ASSERT(this->priv_in_range_or_end(pos));
-      dtl::insert_range_proxy<Allocator, FwdIt, T*> proxy(first);
+      dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
    }
    #endif
@@ -1977,7 +2011,7 @@ class vector
       BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
                    num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
       (void)last;
-      dtl::insert_range_proxy<Allocator, InIt, T*> proxy(first);
+      dtl::insert_range_proxy<allocator_type, InIt, T*> proxy(first);
       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
    }
    #endif
@@ -2035,9 +2069,10 @@ class vector
    //!   plus linear to the elements between pos and the last element.
    iterator erase(const_iterator first, const_iterator last)
    {
-      BOOST_ASSERT(first == last ||
-         (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
       if (first != last){
+         BOOST_ASSERT(this->priv_in_range(first));
+         BOOST_ASSERT(this->priv_in_range_or_end(last));
+         BOOST_ASSERT(first < last);
          T* const old_end_ptr = this->priv_raw_end();
          T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
          T* const last_ptr  = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
@@ -2055,9 +2090,9 @@ class vector
    BOOST_CONTAINER_FORCEINLINE void swap(vector& x)
       BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
                                     || allocator_traits_type::is_always_equal::value) &&
-                                    !dtl::is_version<Allocator, 0>::value))
+                                    !dtl::is_version<allocator_type, 0>::value))
    {
-      this->priv_swap(x, dtl::bool_<dtl::is_version<Allocator, 0>::value>());
+      this->priv_swap(x, dtl::bool_<dtl::is_version<allocator_type, 0>::value>());
    }
 
    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -2069,12 +2104,12 @@ class vector
    //! <b>Complexity</b>: Linear
    //!
    //! <b>Note</b>: Non-standard extension to support static_vector
-   template<class OtherAllocator>
-   BOOST_CONTAINER_FORCEINLINE void swap(vector<T, OtherAllocator> & x
+   template<class OtherA>
+   BOOST_CONTAINER_FORCEINLINE void swap(vector<T, OtherA, Options> & x
             , typename dtl::enable_if_and
                      < void
-                     , dtl::is_version<OtherAllocator, 0>
-                     , dtl::is_different<OtherAllocator, allocator_type>
+                     , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
+                     , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
                      >::type * = 0
             )
    {  this->m_holder.deep_swap(x.m_holder); }
@@ -2180,7 +2215,7 @@ class vector
          this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
       }
       else{
-         iterator pos(this->insert(this->cend(), first, last));
+         this->insert(this->cend(), first, last);
          T *const raw_beg = this->priv_raw_begin();
          T *const raw_end = this->priv_raw_end();
          T *const raw_pos = raw_beg + s;
@@ -2195,11 +2230,11 @@ class vector
    template<class InputIt, class Compare>
    BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last, Compare comp)
    {
-      size_type const s = this->size();
+      size_type const old_size = this->size();
       this->priv_set_difference_back(first, last, comp);
       T *const raw_beg = this->priv_raw_begin();
       T *const raw_end = this->priv_raw_end();
-      T *raw_pos = raw_beg + s;
+      T *raw_pos = raw_beg + old_size;
       boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
    }
 
@@ -2276,14 +2311,14 @@ class vector
 
          if (comp(*first1, *first2)) {
             this->emplace_back(*first1);
-            //Reallocation happened, update range
             T * const raw_begin = this->priv_raw_begin();
-            if(old_first2 != raw_begin){
+            if(old_first2 != raw_begin)
+            {
+               //Reallocation happened, update range
                first2 = raw_begin + (first2 - old_first2);
-               last2  = first2 + (last2 - old_first2);
+               last2  = raw_begin + (last2 - old_first2);
                old_first2 = raw_begin;
             }
-
             ++first1;
          }
          else {
@@ -2298,7 +2333,7 @@ class vector
    template<class FwdIt, class Compare>
    BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
    {
-      throw_bad_alloc();
+      alloc_holder_t::on_capacity_overflow();
    }
 
    template<class FwdIt, class Compare, class Version>
@@ -2348,7 +2383,9 @@ class vector
       pointer const old_p     = this->m_holder.start();
       size_type const old_cap = this->m_holder.capacity();
       boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
-      this->m_holder.deallocate(old_p, old_cap);
+      if (old_cap > 0) {
+         this->m_holder.deallocate(old_p, old_cap);
+      }
       this->m_holder.m_size = old_size + added;
       this->m_holder.start(new_storage);
       this->m_holder.capacity(new_cap);
@@ -2369,14 +2406,14 @@ class vector
       return static_cast<size_type>(p - this->m_holder.start());
    }
 
-   template<class OtherAllocator>
-   void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+   template<class OtherA>
+   void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
       , typename dtl::enable_if_c
-         < dtl::is_version<OtherAllocator, 0>::value >::type * = 0)
+         < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
    {
-      if(!dtl::is_same<OtherAllocator, allocator_type>::value &&
+      if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
           this->capacity() < x.size()){
-         throw_bad_alloc();
+         alloc_holder_t::on_capacity_overflow();
       }
       T* const this_start  = this->priv_raw_begin();
       T* const other_start = x.priv_raw_begin();
@@ -2386,34 +2423,29 @@ class vector
       this->m_holder.m_size = other_sz;
    }
 
-   template<class OtherAllocator>
-   void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+   template<class OtherA>
+   void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
       , typename dtl::disable_if_or
          < void
-         , dtl::is_version<OtherAllocator, 0>
-         , dtl::is_different<OtherAllocator, allocator_type>
+         , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
+         , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
          >::type * = 0)
    {
-      //for move assignment, no aliasing (&x != this) is assummed.
-      BOOST_ASSERT(this != &x);
+      //for move assignment, no aliasing (&x != this) is assumed.
+      //x.size() == 0 is allowed for buggy std libraries.
+      BOOST_ASSERT(this != &x || x.size() == 0);
       allocator_type &this_alloc = this->m_holder.alloc();
       allocator_type &x_alloc    = x.m_holder.alloc();
       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
 
       const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
-      const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc,   propagate_alloc);
-      const bool are_both_propagable  = is_propagable_from_x && is_propagable_from_t;
 
       //Resources can be transferred if both allocators are
       //going to be equal after this function (either propagated or already equal)
-      if(are_both_propagable){
-         //Destroy objects but retain memory in case x reuses it in the future
+      if(is_propagable_from_x){
          this->clear();
-         this->m_holder.swap_resources(x.m_holder);
-      }
-      else if(is_propagable_from_x){
-         this->clear();
-         this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
+         if(BOOST_LIKELY(!!this->m_holder.m_start))
+            this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
          this->m_holder.steal_resources(x.m_holder);
       }
       //Else do a one by one move
@@ -2426,14 +2458,14 @@ class vector
       dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
    }
 
-   template<class OtherAllocator>
-   void priv_copy_assign(const vector<T, OtherAllocator> &x
+   template<class OtherA>
+   void priv_copy_assign(const vector<T, OtherA, Options> &x
       , typename dtl::enable_if_c
-         < dtl::is_version<OtherAllocator, 0>::value >::type * = 0)
+         < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
    {
-      if(!dtl::is_same<OtherAllocator, allocator_type>::value &&
+      if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
          this->capacity() < x.size()){
-         throw_bad_alloc();
+         alloc_holder_t::on_capacity_overflow();
       }
       T* const this_start  = this->priv_raw_begin();
       T* const other_start = x.priv_raw_begin();
@@ -2443,13 +2475,13 @@ class vector
       this->m_holder.m_size = other_sz;
    }
 
-   template<class OtherAllocator>
+   template<class OtherA>
    typename dtl::disable_if_or
       < void
-      , dtl::is_version<OtherAllocator, 0>
-      , dtl::is_different<OtherAllocator, allocator_type>
+      , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
+      , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
       >::type
-      priv_copy_assign(const vector<T, OtherAllocator> &x)
+      priv_copy_assign(const vector<T, OtherA, Options> &x)
    {
       allocator_type &this_alloc     = this->m_holder.alloc();
       const allocator_type &x_alloc  = x.m_holder.alloc();
@@ -2477,6 +2509,9 @@ class vector
          this->m_holder.swap_resources(x.m_holder);
       }
       else{
+         if (BOOST_UNLIKELY(&x == this))
+            return;
+
          //Else swap element by element...
          bool const t_smaller = this->size() < x.size();
          vector &sml = t_smaller ? *this : x;
@@ -2499,11 +2534,11 @@ class vector
    }
 
    void priv_reserve_no_capacity(size_type, version_0)
-   {  throw_bad_alloc();  }
+   {  alloc_holder_t::on_capacity_overflow();  }
 
-   dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
+   dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
    {
-      return dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+      return dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*>
          (::boost::make_move_iterator((T *)0));
    }
 
@@ -2595,14 +2630,14 @@ class vector
    {
       BOOST_ASSERT(this->priv_in_range_or_end(p));
       return this->priv_forward_range_insert
-         ( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x)));
+         ( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, allocator_type>(::boost::forward<U>(x)));
    }
 
-   dtl::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x)
-   {  return dtl::insert_copy_proxy<Allocator, T*> (x);  }
+   BOOST_CONTAINER_FORCEINLINE dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
+   {  return dtl::insert_copy_proxy<allocator_type, T*> (x);  }
 
-   dtl::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
-   {  return dtl::insert_move_proxy<Allocator, T*> (x);  }
+   BOOST_CONTAINER_FORCEINLINE dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
+   {  return dtl::insert_move_proxy<allocator_type, T*> (x);  }
 
    template <class U>
    void priv_push_back(BOOST_FWD_REF(U) u)
@@ -2620,14 +2655,14 @@ class vector
       }
    }
 
-   BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
-   {  return dtl::insert_n_copies_proxy<Allocator, T*>(x);   }
+   BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<allocator_type, T*> priv_resize_proxy(const T &x)
+   {  return dtl::insert_n_copies_proxy<allocator_type, T*>(x);   }
 
-   BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
-   {  return dtl::insert_default_initialized_n_proxy<Allocator, T*>();  }
+   BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(default_init_t)
+   {  return dtl::insert_default_initialized_n_proxy<allocator_type, T*>();  }
 
-   BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
-   {  return dtl::insert_value_initialized_n_proxy<Allocator, T*>(); }
+   BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(value_init_t)
+   {  return dtl::insert_value_initialized_n_proxy<allocator_type, T*>(); }
 
    template <class U>
    void priv_resize(size_type new_size, const U& u)
@@ -2652,7 +2687,8 @@ class vector
       if(cp){
          const size_type sz = this->size();
          if(!sz){
-            this->m_holder.deallocate(this->m_holder.m_start, cp);
+            if(BOOST_LIKELY(!!this->m_holder.m_start))
+               this->m_holder.deallocate(this->m_holder.m_start, cp);
             this->m_holder.m_start     = pointer();
             this->m_holder.m_capacity  = 0;
          }
@@ -2678,7 +2714,8 @@ class vector
       if(cp){
          const size_type sz = this->size();
          if(!sz){
-            this->m_holder.deallocate(this->m_holder.m_start, cp);
+            if(BOOST_LIKELY(!!this->m_holder.m_start))
+               this->m_holder.deallocate(this->m_holder.m_start, cp);
             this->m_holder.m_start     = pointer();
             this->m_holder.m_capacity  = 0;
          }
@@ -2700,7 +2737,7 @@ class vector
    iterator priv_forward_range_insert_no_capacity
       (const pointer &pos, const size_type, const InsertionProxy , version_0)
    {
-      throw_bad_alloc();
+      alloc_holder_t::on_capacity_overflow();
       return iterator(pos);
    }
 
@@ -2800,7 +2837,7 @@ class vector
 
       if (n > remaining){
          //This will trigger an error
-         throw_bad_alloc();
+         alloc_holder_t::on_capacity_overflow();
       }
       this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
       return this->end();
@@ -3352,6 +3389,19 @@ class vector
    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
 };
 
+#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
+
+template <typename InputIterator>
+vector(InputIterator, InputIterator) ->
+   vector<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+vector(InputIterator, InputIterator, Allocator const&) ->
+   vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
+
+#endif
+
+
 }} //namespace boost::container
 
 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -3360,11 +3410,12 @@ namespace boost {
 
 //!has_trivial_destructor_after_move<> == true_type
 //!specialization for optimizations
-template <class T, class Allocator>
-struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
+template <class T, class Allocator, class Options>
+struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
 {
-   typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
-   static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+   typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
+   typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
+   static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
                              ::boost::has_trivial_destructor_after_move<pointer>::value;
 };