text: //////////////////////////////////////////////////////////////////////////////
  //
  // (C) Copyright Ion Gaztanaga 2005-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.
  //
  //////////////////////////////////////////////////////////////////////////////
  
  #ifndef BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
  #define BOOST_CONTAINERS_CONTAINERS_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 <cstddef>
  #include <memory>
  #include <algorithm>
  #include <stdexcept>
  #include <iterator>
  #include <utility>
  #include <boost/detail/no_exceptions_support.hpp>
  #include <boost/type_traits/has_trivial_destructor.hpp>
  #include <boost/type_traits/has_trivial_copy.hpp>
  #include <boost/type_traits/has_trivial_assign.hpp>
  #include <boost/type_traits/has_nothrow_copy.hpp>
  #include <boost/type_traits/has_nothrow_assign.hpp>
  #include <boost/move/move_helpers.hpp>
  #include <boost/container/detail/version_type.hpp>
  #include <boost/container/detail/allocation_type.hpp>
  #include <boost/container/detail/utilities.hpp>
  #include <boost/container/detail/iterators.hpp>
  #include <boost/container/detail/algorithms.hpp>
  #include <boost/container/detail/destroyers.hpp>
  #include <boost/container/container_fwd.hpp>
  #include <boost/move/move.hpp>
  #include <boost/pointer_to_other.hpp>
  #include <boost/container/detail/mpl.hpp>
  #include <boost/container/detail/advanced_insert_int.hpp>
  
  namespace boost {
  namespace container {
  
  /// @cond
  
  namespace containers_detail {
  
  //! Const vector_iterator used to iterate through a vector. 
  template <class Pointer>
  class vector_const_iterator
     : public std::iterator<std::random_access_iterator_tag
                            ,const typename std::iterator_traits<Pointer>::value_type
                            ,typename std::iterator_traits<Pointer>::difference_type
                            ,typename boost::pointer_to_other
                                <Pointer
                                ,const typename std::iterator_traits<Pointer>::value_type
                                >::type
                            ,const typename std::iterator_traits<Pointer>::value_type &>
  {
     public:
     typedef typename std::iterator_traits<Pointer>::value_type  value_type;
     typedef typename std::iterator_traits<Pointer>::difference_type   difference_type;
     typedef typename boost::pointer_to_other<Pointer, value_type>::type      pointer;
     typedef const value_type&                                               reference;
  
     /// @cond
     protected:
     Pointer m_ptr;
  
     public:
     Pointer get_ptr() const    {  return   m_ptr;  }
     explicit vector_const_iterator(Pointer ptr)  : m_ptr(ptr){}
     /// @endcond
  
     public:
  
     //Constructors
     vector_const_iterator() : m_ptr(0){}
  
     //Pointer like operators
     reference operator*()   const  
     {  return *m_ptr;  }
  
     const value_type * operator->()  const  
     {  return  containers_detail::get_pointer(m_ptr);  }
  
     reference operator[](difference_type off) const
     {  return m_ptr[off];   }
  
     //Increment / Decrement
     vector_const_iterator& operator++()       
     { ++m_ptr;  return *this; }
  
     vector_const_iterator operator++(int)      
     {  Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp);  }
  
     vector_const_iterator& operator--()
     {  --m_ptr; return *this;  }
  
     vector_const_iterator operator--(int)
     {  Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); }
  
     //Arithmetic
     vector_const_iterator& operator+=(difference_type off)
     {  m_ptr += off; return *this;   }
  
     vector_const_iterator operator+(difference_type off) const
     {  return vector_const_iterator(m_ptr+off);  }
  
     friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right)
     {  return vector_const_iterator(off + right.m_ptr); }
  
     vector_const_iterator& operator-=(difference_type off)
     {  m_ptr -= off; return *this;   }
  
     vector_const_iterator operator-(difference_type off) const
     {  return vector_const_iterator(m_ptr-off);  }
  
     difference_type operator-(const vector_const_iterator& right) const
     {  return m_ptr - right.m_ptr;   }
  
     //Comparison operators
     bool operator==   (const vector_const_iterator& r)  const
     {  return m_ptr == r.m_ptr;  }
  
     bool operator!=   (const vector_const_iterator& r)  const
     {  return m_ptr != r.m_ptr;  }
  
     bool operator<    (const vector_const_iterator& r)  const
     {  return m_ptr < r.m_ptr;  }
  
     bool operator<=   (const vector_const_iterator& r)  const
     {  return m_ptr <= r.m_ptr;  }
  
     bool operator>    (const vector_const_iterator& r)  const
     {  return m_ptr > r.m_ptr;  }
  
     bool operator>=   (const vector_const_iterator& r)  const
     {  return m_ptr >= r.m_ptr;  }
  };
  
  //! Iterator used to iterate through a vector
  template <class Pointer>
  class vector_iterator
     :  public vector_const_iterator<Pointer>
  {
     public:
     explicit vector_iterator(Pointer ptr)
        : vector_const_iterator<Pointer>(ptr)
     {}
  
     public:
     typedef typename std::iterator_traits<Pointer>::value_type        value_type;
     typedef typename vector_const_iterator<Pointer>::difference_type  difference_type;
     typedef Pointer                                                   pointer;
     typedef value_type&                                               reference;
  
     //Constructors
     vector_iterator()
     {}
  
     //Pointer like operators
     reference operator*()  const  
     {  return *this->m_ptr;  }
  
     value_type* operator->() const  
     {  return  containers_detail::get_pointer(this->m_ptr);  }
  
     reference operator[](difference_type off) const 
     {  return this->m_ptr[off];   }
  
     //Increment / Decrement
     vector_iterator& operator++()  
     {  ++this->m_ptr; return *this;  }
  
     vector_iterator operator++(int)
     {  pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp);  }
     
     vector_iterator& operator--()
     {  --this->m_ptr; return *this;  }
  
     vector_iterator operator--(int)
     {  vector_iterator tmp = *this; --*this; return vector_iterator(tmp); }
  
     // Arithmetic
     vector_iterator& operator+=(difference_type off)
     {  this->m_ptr += off;  return *this;  }
  
     vector_iterator operator+(difference_type off) const
     {  return vector_iterator(this->m_ptr+off);  }
  
     friend vector_iterator operator+(difference_type off, const vector_iterator& right)
     {  return vector_iterator(off + right.m_ptr); }
  
     vector_iterator& operator-=(difference_type off)
     {  this->m_ptr -= off; return *this;   }
  
     vector_iterator operator-(difference_type off) const
     {  return vector_iterator(this->m_ptr-off);  }
  
     difference_type operator-(const vector_const_iterator<Pointer>& right) const
     {  return static_cast<const vector_const_iterator<Pointer>&>(*this) - right;   }
  };
  
  template <class T, class A>
  struct vector_value_traits
  {
     typedef T value_type;
     typedef A allocator_type;
     static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
     static const bool trivial_dctr_after_move = trivial_dctr;
        //::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
     static const bool trivial_copy = has_trivial_copy<value_type>::value;
     static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
     static const bool trivial_assign = has_trivial_assign<value_type>::value;
     static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
  
     //This is the anti-exception array destructor
     //to deallocate values already constructed
     typedef typename containers_detail::if_c
        <trivial_dctr
        ,containers_detail::null_scoped_destructor_n<allocator_type>
        ,containers_detail::scoped_destructor_n<allocator_type>
        >::type   OldArrayDestructor;
     //This is the anti-exception array destructor
     //to destroy objects created with copy construction
     typedef typename containers_detail::if_c
        <nothrow_copy
        ,containers_detail::null_scoped_destructor_n<allocator_type>
        ,containers_detail::scoped_destructor_n<allocator_type>
        >::type   ArrayDestructor;
     //This is the anti-exception array deallocator
     typedef typename containers_detail::if_c
        <nothrow_copy
        ,containers_detail::null_scoped_array_deallocator<allocator_type>
        ,containers_detail::scoped_array_deallocator<allocator_type>
        >::type   ArrayDeallocator;
  };
  
  //!This struct deallocates and allocated memory
  template <class A>
  struct vector_alloc_holder 
  {
     typedef typename A::pointer      pointer;
     typedef typename A::size_type    size_type;
     typedef typename A::value_type   value_type;
     typedef vector_value_traits<value_type, A> value_traits;
  
     //Constructor, does not throw
     vector_alloc_holder(const A &a)
        : members_(a)
     {}
  
     //Destructor
     ~vector_alloc_holder()
     {
        this->prot_destroy_all();
        this->prot_deallocate();
     }
  
     typedef containers_detail::integral_constant<unsigned, 1>      allocator_v1;
     typedef containers_detail::integral_constant<unsigned, 2>      allocator_v2;
     typedef containers_detail::integral_constant<unsigned,
        boost::container::containers_detail::version<A>::value> alloc_version;
     std::pair<pointer, bool>
        allocation_command(allocation_type command,
                           size_type limit_size, 
                           size_type preferred_size,
                           size_type &received_size, const pointer &reuse = 0)
     {
        return allocation_command(command, limit_size, preferred_size,
                                 received_size, reuse, alloc_version());
     }
  
     std::pair<pointer, bool>
        allocation_command(allocation_type command,
                           size_type limit_size, 
                           size_type preferred_size,
                           size_type &received_size,
                           const pointer &reuse,
                           allocator_v1)
     {
        (void)limit_size;
        (void)reuse;
        if(!(command & allocate_new))
           return std::pair<pointer, bool>(pointer(0), false);
        received_size = preferred_size;
        return std::make_pair(this->alloc().allocate(received_size), false);
     }
  
     std::pair<pointer, bool>
        allocation_command(allocation_type command,
                           size_type limit_size, 
                           size_type preferred_size,
                           size_type &received_size,
                           const pointer &reuse,
                           allocator_v2)
     {
        return this->alloc().allocation_command
           (command, limit_size, preferred_size, received_size, reuse);
     }
  
     size_type next_capacity(size_type additional_objects) const
     {  return get_next_capacity(this->alloc().max_size(), this->members_.m_capacity, additional_objects);  }
  
     struct members_holder
        : public A
     {
        private:
        members_holder(const members_holder&);
  
        public:
        members_holder(const A &alloc)
           :  A(alloc), m_start(0), m_size(0), m_capacity(0)
        {}
  
        pointer     m_start;
        size_type   m_size;
        size_type   m_capacity;
     } members_;
  
     A &alloc()
     {  return members_;  }
  
     const A &alloc() const
     {  return members_;  }
  
     protected:
     void prot_deallocate()
     {
        if(!this->members_.m_capacity)   return;
        this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
        this->members_.m_start     = 0;
        this->members_.m_size      = 0;
        this->members_.m_capacity  = 0;
     }
  
     void destroy(value_type* p)
     {
        if(!value_traits::trivial_dctr)
           containers_detail::get_pointer(p)->~value_type();
     }
  
     void destroy_n(value_type* p, size_type n)
     {
        if(!value_traits::trivial_dctr)
           for(; n--; ++p)   p->~value_type();
     }
  
     void prot_destroy_all()
     {
        this->destroy_n(containers_detail::get_pointer(this->members_.m_start), this->members_.m_size);
        this->members_.m_size = 0;
     }
  };
  
  }  //namespace containers_detail {
  /// @endcond
  
  //! \class vector
  //! A vector is a sequence that supports random access to elements, constant 
  //! time insertion and removal of elements at the end, and linear time insertion 
  //! and removal of elements at the beginning or in the middle. The number of 
  //! elements in a vector may vary dynamically; memory management is automatic.
  //! boost::container::vector is similar to std::vector but it's compatible
  //! with shared memory and memory mapped files.
  #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  template <class T, class A = std::allocator<T> >
  #else
  template <class T, class A>
  #endif
  class vector : private containers_detail::vector_alloc_holder<A>
  {
     /// @cond
     typedef vector<T, A>                   self_t;
     typedef containers_detail::vector_alloc_holder<A> base_t;
     /// @endcond
     public:
     //! The type of object, T, stored in the vector
     typedef T                                       value_type;
     //! Pointer to T
     typedef typename A::pointer                     pointer;
     //! Const pointer to T
     typedef typename A::const_pointer               const_pointer;
     //! Reference to T
     typedef typename A::reference                   reference;
     //! Const reference to T
     typedef typename A::const_reference             const_reference;
     //! An unsigned integral type
     typedef typename A::size_type                   size_type;
     //! A signed integral type
     typedef typename A::difference_type             difference_type;
     //! The allocator type
     typedef A                                       allocator_type;
     //! The random access iterator
     typedef containers_detail::vector_iterator<pointer>        iterator;
     //! The random access const_iterator
     typedef containers_detail::vector_const_iterator<pointer>  const_iterator;
  
     //! Iterator used to iterate backwards through a vector. 
     typedef std::reverse_iterator<iterator>   
        reverse_iterator;
     //! Const iterator used to iterate backwards through a vector. 
     typedef std::reverse_iterator<const_iterator>                 
        const_reverse_iterator;
     //! The stored allocator type
     typedef allocator_type                          stored_allocator_type;
  
     /// @cond
     private:
     BOOST_COPYABLE_AND_MOVABLE(vector)
     typedef containers_detail::advanced_insert_aux_int<T, T*>    advanced_insert_aux_int_t;
     typedef containers_detail::vector_value_traits<value_type, A> value_traits;
  
     typedef typename base_t::allocator_v1           allocator_v1;
     typedef typename base_t::allocator_v2           allocator_v2;
     typedef typename base_t::alloc_version          alloc_version;
  
     typedef constant_iterator<T, difference_type>   cvalue_iterator;
     typedef repeat_iterator<T, difference_type>     repeat_it;
     typedef boost::move_iterator<repeat_it>         repeat_move_it;
     /// @endcond
  
     public:
  
     //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
     //! 
     //! <b>Throws</b>: If allocator_type's copy constructor throws.
     //! 
     //! <b>Complexity</b>: Constant.
     explicit vector(const A& a = A())
        : base_t(a)
     {}
  
     //! <b>Effects</b>: Constructs a 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 vector(size_type n) 
        :  base_t(allocator_type())
     {
        //Allocate
        size_type real_cap;
        std::pair<pointer, bool> ret =
           this->allocation_command(allocate_new, n, n, real_cap, this->members_.m_start);
        T *new_mem = containers_detail::get_pointer(ret.first);
        //Anti-exception rollback
        typename value_traits::ArrayDeallocator scoped_alloc(new_mem, this->alloc(), real_cap);
        //Default constructor
        containers_detail::default_construct_aux_proxy<T, T*, size_type> proxy(n);
        proxy.uninitialized_copy_all_to(new_mem);
        //All ok, commit
        this->members_.m_start = ret.first;
        this->members_.m_size  = n;
        this->members_.m_capacity = real_cap;
        scoped_alloc.release();
     }
  
     //! <b>Effects</b>: Constructs a 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.
     vector(size_type n, const T& value, const allocator_type& a = allocator_type()) 
        :  base_t(a)
     {  this->insert(this->cend(), n, value); }
  
     //! <b>Effects</b>: Copy constructs a vector.
     //!
     //! <b>Postcondition</b>: x == *this.
     //! 
     //! <b>Complexity</b>: Linear to the elements x contains.
     vector(const vector<T, A>& x) 
        :  base_t(static_cast<const base_t&>(x).alloc())
     {  *this = x;  }
  
     //! <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.
     vector(BOOST_RV_REF(vector) mx) 
        :  base_t(static_cast<base_t&>(mx).alloc())
     {  this->swap(mx);   }
  
     //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
     //!   and inserts a copy of the range [first, last) in the 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 InIt>
     vector(InIt first, InIt last, const allocator_type& a = allocator_type())
        :  base_t(a)
     {  this->assign(first, last); }
  
     //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
     //!   and used memory is deallocated.
     //!
     //! <b>Throws</b>: Nothing.
     //!
     //! <b>Complexity</b>: Linear to the number of elements.
     ~vector() 
     {} //vector_alloc_holder clears the data
  
     //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     iterator begin()      
     { return iterator(this->members_.m_start); }
  
     //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_iterator begin() const
     { return const_iterator(this->members_.m_start); }
  
     //! <b>Effects</b>: Returns an iterator to the end of the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     iterator end()        
     { return iterator(this->members_.m_start + this->members_.m_size); }
  
     //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_iterator end()   const
     { return this->cend(); }
  
     //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning 
     //! of the reversed 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 vector. 
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_reverse_iterator rbegin()const
     { return this->crbegin(); }
  
     //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
     //! of the reversed 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 vector. 
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_reverse_iterator rend()  const
     { return this->crend(); }
  
     //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_iterator cbegin() const
     { return const_iterator(this->members_.m_start); }
  
     //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_iterator cend()   const
     { return const_iterator(this->members_.m_start + this->members_.m_size); }
  
     //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning 
     //! of the reversed vector. 
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_reverse_iterator crbegin()const
     { return const_reverse_iterator(this->end());}
  
     //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
     //! of the reversed vector. 
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_reverse_iterator crend()  const
     { return const_reverse_iterator(this->begin()); }
  
     //! <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 *this->members_.m_start; }
  
     //! <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 *this->members_.m_start; }
  
     //! <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 this->members_.m_start[this->members_.m_size - 1]; }
  
     //! <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 this->members_.m_start[this->members_.m_size - 1]; }
  
     //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
     //!   For a non-empty vector, data() == &front().
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     pointer data()        
     { return this->members_.m_start; }
  
     //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
     //!   For a non-empty vector, data() == &front().
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     const_pointer data()  const 
     { return this->members_.m_start; }
  
     //! <b>Effects</b>: Returns the number of the elements contained in the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     size_type size() const 
     { return this->members_.m_size; }
  
     //! <b>Effects</b>: Returns the largest possible size of the vector.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     size_type max_size() const 
     { return this->alloc().max_size(); }
  
     //! <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 
     { return this->members_.m_capacity; }
  
     //! <b>Effects</b>: Returns true if the vector contains no elements.
     //! 
     //! <b>Throws</b>: Nothing.
     //! 
     //! <b>Complexity</b>: Constant.
     bool empty() const 
     { return !this->members_.m_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 this->members_.m_start[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 this->members_.m_start[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)
     { this->priv_check_range(n); return this->members_.m_start[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
     { this->priv_check_range(n); return this->members_.m_start[n]; }
  
     //! <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 this->alloc();  }
  
     const stored_allocator_type &get_stored_allocator() const 
     {  return this->alloc(); }
  
     stored_allocator_type &get_stored_allocator()
     {  return this->alloc(); }
  
     //! <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 or T's copy/move constructor throws.
     void reserve(size_type new_cap)
     {
        if (this->capacity() < new_cap){
           //There is not enough memory, allocate a new
           //buffer or expand the old one.
           bool same_buffer_start;
           size_type real_cap = 0;
           std::pair<pointer, bool> ret =
              this->allocation_command
                 (allocate_new | expand_fwd | expand_bwd,
                    new_cap, new_cap, real_cap, this->members_.m_start);
  
           //Check for forward expansion
           same_buffer_start = ret.second && this->members_.m_start == ret.first;
           if(same_buffer_start){
              #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
              ++this->num_expand_fwd;
              #endif
              this->members_.m_capacity  = real_cap;
           }
  
           //If there is no forward expansion, move objects
           else{
              //We will reuse insert code, so create a dummy input iterator
              T *dummy_it(containers_detail::get_pointer(this->members_.m_start));
              containers_detail::advanced_insert_aux_proxy<T, boost::move_iterator<T*>, T*>
                 proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
              //Backwards (and possibly forward) expansion
              if(ret.second){
                 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
                 ++this->num_expand_bwd;
                 #endif
                 this->priv_range_insert_expand_backwards
                    ( containers_detail::get_pointer(ret.first)
                    , real_cap
                    , containers_detail::get_pointer(this->members_.m_start)
                    , 0
                    , proxy);
              }
              //New buffer
              else{
                 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
                 ++this->num_alloc;
                 #endif
                 this->priv_range_insert_new_allocation
                    ( containers_detail::get_pointer(ret.first)
                    , real_cap
                    , containers_detail::get_pointer(this->members_.m_start)
                    , 0
                    , proxy);
              }
           }
        }
     }
  
     //! <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.
     vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
     {
        if (&x != this){
           this->assign(x.members_.m_start, x.members_.m_start + x.members_.m_size);
        }
        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.
     vector& operator=(BOOST_RV_REF(vector) x)
     {
        if (&x != this){
           this->swap(x);
           x.clear();
        }
        return *this;
     }
  
     //! <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 value_type& val)
     {  this->assign(cvalue_iterator(val, n), cvalue_iterator());   }
  
     //! <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 <class InIt>
     void assign(InIt first, InIt last) 
     {
        //Dispatch depending on integer/iterator
        const bool aux_boolean = containers_detail::is_convertible<InIt, size_type>::value;
        typedef containers_detail::bool_<aux_boolean> Result;
        this->priv_assign_dispatch(first, last, Result());
     }
  
     #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
     //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
     //!
     //! <b>Throws</b>: If memory allocation throws or
     //!   T's copy constructor throws.
     //!
     //! <b>Complexity</b>: Amortized constant time.
     void push_back(const T &x);
  
     //! <b>Effects</b>: Constructs a new element in the end of the 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(T &&x);
     #else
     BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
     #endif
  
  /*
     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>
     typename containers_detail::enable_if_c
                       <!::boost::has_move_emulation_enabled<U>::value &&
                       containers_detail::is_same<T, U>::value
                       >::type
     push_back(const U &u)
     { return priv_push_back(u); }
  
     #endif
  
     //! <b>Effects</b>: Constructs a new element in the end of the 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) x)
     {
        if (this->members_.m_size < this->members_.m_capacity){
           //There is more memory, just construct a new object at the end
           new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::move(x));
           ++this->members_.m_size;
        }
        else{
           this->insert(this->cend(), ::boost::move(x));
        }
     }
  */
     //! <b>Effects</b>: Constructs a new element in the end of the vector
     //!   and moves the resources of mx to this new element.
     //!
     //! <b>Throws</b>: If memory allocation throws.
     //!
     //! <b>Complexity</b>: Amortized constant time.
  
  
     #if defined(BOOST_CONTAINERS_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 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)
     {
        T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
        if (this->members_.m_size < this->members_.m_capacity){
           //There is more memory, just construct a new object at the end
           new((void*)(back_pos))value_type(::boost::forward<Args>(args)...);
           ++this->members_.m_size;
        }
        else{
           typedef containers_detail::advanced_insert_aux_emplace<T, T*, Args...> type;
           type &&proxy = type(::boost::forward<Args>(args)...);
           priv_range_insert(back_pos, 1, proxy);
        }
     }
  
     //! <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 containers_detail::advanced_insert_aux_emplace<T, T*, Args...> type;
        type &&proxy = type(::boost::forward<Args>(args)...);
        priv_range_insert(position.get_ptr(), 1, proxy);
        return iterator(this->members_.m_start + pos_n);
     }
  
     #else
  
     void emplace_back()
     {
        T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
        if (this->members_.m_size < this->members_.m_capacity){
           //There is more memory, just construct a new object at the end
           new((void*)(back_pos))value_type();
           ++this->members_.m_size;
        }
        else{
           containers_detail::advanced_insert_aux_emplace<value_type, T*> proxy;
           priv_range_insert(back_pos, 1, proxy);
        }
     }
  
     iterator emplace(const_iterator position)
     {
        size_type pos_n = position - cbegin();
        containers_detail::advanced_insert_aux_emplace<value_type, T*> proxy;
        priv_range_insert(containers_detail::get_pointer(position.get_ptr()), 1, proxy);
        return iterator(this->members_.m_start + pos_n);
     }
  
     #define BOOST_PP_LOCAL_MACRO(n)                                                              \
     template<BOOST_PP_ENUM_PARAMS(n, class P)>                                                   \
     void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))                       \
     {                                                                                            \
        T* back_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;        \
        if (this->members_.m_size < this->members_.m_capacity){                                   \
           new((void*)(back_pos))value_type                                                       \
              (BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                           \
           ++this->members_.m_size;                                                               \
        }                                                                                         \
        else{                                                                                     \
           containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)     \
              <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)>                                        \
                 proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                   \
           priv_range_insert(back_pos, 1, proxy);                                                 \
        }                                                                                         \
     }                                                                                            \
                                                                                                  \
     template<BOOST_PP_ENUM_PARAMS(n, class P)>                                                   \
     iterator emplace(const_iterator pos, BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_LIST, _))    \
     {                                                                                            \
        size_type pos_n = pos - cbegin();                                                         \
        containers_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg)        \
           <value_type, T*, BOOST_PP_ENUM_PARAMS(n, P)>                                           \
              proxy(BOOST_PP_ENUM(n, BOOST_CONTAINERS_PP_PARAM_FORWARD, _));                      \
        priv_range_insert(containers_detail::get_pointer(pos.get_ptr()), 1, proxy);               \
        return iterator(this->members_.m_start + pos_n);                                          \
     }                                                                                            \
     //!
     #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINERS_MAX_CONSTRUCTOR_PARAMETERS)
     #include BOOST_PP_LOCAL_ITERATE()
  
     #endif   //#ifdef BOOST_CONTAINERS_PERFECT_FORWARDING
    
     //! <b>Effects</b>: Swaps the contents of *this and x.
     //!   If this->allocator_type() != x.allocator_type()
     //!   allocators are also swapped.
     //!
     //! <b>Throws</b>: Nothing.
     //!
     //! <b>Complexity</b>: Constant.
     void swap(vector& x)
     {
        allocator_type &this_al = this->alloc(), &other_al = x.alloc();
        //Just swap internals
        containers_detail::do_swap(this->members_.m_start, x.members_.m_start);
        containers_detail::do_swap(this->members_.m_size, x.members_.m_size);
        containers_detail::do_swap(this->members_.m_capacity, x.members_.m_capacity);
  
        if (this_al != other_al){
           containers_detail::do_swap(this_al, other_al);
        }
     }
  
     #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
     //! <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, const T &x);
  
     //! <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, T &&x);
     #else
     BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
     #endif
  
     //! <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 InIt>
     void insert(const_iterator pos, InIt first, InIt last)
     {
        //Dispatch depending on integer/iterator
        const bool aux_boolean = containers_detail::is_convertible<InIt, size_type>::value;
        typedef containers_detail::bool_<aux_boolean> Result;
        this->priv_insert_dispatch(pos, first, last, Result());
     }
  
     //! <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 p, size_type n, const T& x)
     {  this->insert(p, cvalue_iterator(x, n), cvalue_iterator());  }
  
     //! <b>Effects</b>: Removes the last element from the vector.
     //!
     //! <b>Throws</b>: Nothing.
     //!
     //! <b>Complexity</b>: Constant time.
     void pop_back() 
     {
        //Destroy last element
        --this->members_.m_size;
        this->destroy(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
     }
  
     //! <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) 
     {
        T *pos = containers_detail::get_pointer(position.get_ptr());
        T *beg = containers_detail::get_pointer(this->members_.m_start);
        ::boost::move(pos + 1, beg + this->members_.m_size, pos);
        --this->members_.m_size;
        //Destroy last element
        base_t::destroy(containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
        return iterator(position.get_ptr());
     }
  
     //! <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) 
     {
        if (first != last){   // worth doing, copy down over hole
           T* end_pos = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
           T* ptr = containers_detail::get_pointer(boost::move
              (containers_detail::get_pointer(last.get_ptr())
              ,end_pos
              ,containers_detail::get_pointer(first.get_ptr())
              ));
           size_type destroyed = (end_pos - ptr);
           this->destroy_n(ptr, destroyed);
           this->members_.m_size -= destroyed;
        }
        return iterator(first.get_ptr());
     }
  
     //! <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 new_size, const T& x) 
     {
        pointer finish = this->members_.m_start + this->members_.m_size;
        if (new_size < size()){
           //Destroy last elements
           this->erase(const_iterator(this->members_.m_start + new_size), this->end());
        }
        else{
           //Insert new elements at the end
           this->insert(const_iterator(finish), new_size - this->size(), x);
        }
     }
  
     //! <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 new_size) 
     {
        if (new_size < this->size()){
           //Destroy last elements
           this->erase(const_iterator(this->members_.m_start + new_size), this->end());
        }
        else{
           size_type n = new_size - this->size();
           this->reserve(new_size);
           containers_detail::default_construct_aux_proxy<T, T*, size_type> proxy(n);
           priv_range_insert(this->cend().get_ptr(), n, proxy);
        }
     }
  
     //! <b>Effects</b>: Erases all the elements of the vector.
     //!
     //! <b>Throws</b>: Nothing.
     //!
     //! <b>Complexity</b>: Linear to the number of elements in the vector.
     void clear() 
     {  this->prot_destroy_all();  }
  
     //! <b>Effects</b>: Tries to deallocate the excess of memory created
     //!   with previous allocations. The size of the vector is unchanged
     //!
     //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
     //!
     //! <b>Complexity</b>: Linear to size().
     void shrink_to_fit()
     {  priv_shrink_to_fit(alloc_version());   }
  
     /// @cond
  
     private:
     iterator priv_insert(const_iterator position, const T &x) 
     {
        //Just call more general insert(pos, size, value) and return iterator
        size_type pos_n = position - cbegin();
        this->insert(position, (size_type)1, x);
        return iterator(this->members_.m_start + pos_n);
     }
  
     iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x) 
     {
        //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->members_.m_start + pos_n);
     }
  
     template <class U>
     void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
     {
        if (this->members_.m_size < this->members_.m_capacity){
           //There is more memory, just construct a new object at the end
           new((void*)containers_detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(::boost::forward<U>(x));
           ++this->members_.m_size;
        }
        else{
           this->insert(this->cend(), ::boost::forward<U>(x));
        }
     }
  
     void priv_shrink_to_fit(allocator_v1)
     {
        if(this->members_.m_capacity){
           if(!size()){
              this->prot_deallocate();
           }
           else{
              //Allocate a new buffer.
              size_type real_cap = 0;
              std::pair<pointer, bool> ret =
                 this->allocation_command
                    (allocate_new, this->size(), this->size(), real_cap, this->members_.m_start);
              if(real_cap < this->capacity()){
                 //We will reuse insert code, so create a dummy input iterator
                 T *dummy_it(containers_detail::get_pointer(this->members_.m_start));
                 containers_detail::advanced_insert_aux_proxy<T, boost::move_iterator<T*>, T*>
                    proxy(::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
                 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
                 ++this->num_alloc;
                 #endif
                 this->priv_range_insert_new_allocation
                    ( containers_detail::get_pointer(ret.first)
                    , real_cap
                    , containers_detail::get_pointer(this->members_.m_start)
                    , 0
                    , proxy);
              }
              else{
                 this->alloc().deallocate(ret.first, real_cap);
              }
           }
        }
     }
  
     void priv_shrink_to_fit(allocator_v2)
     {
        if(this->members_.m_capacity){
           if(!size()){
              this->prot_deallocate();
           }
           else{
              size_type received_size;
              if(this->alloc().allocation_command
                 ( shrink_in_place | nothrow_allocation
                 , this->capacity(), this->size()
                 , received_size,   this->members_.m_start).first){
                 this->members_.m_capacity = received_size;
                 #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
                 ++this->num_shrink;
                 #endif
              }
           }
        }
     }
  
     template <class FwdIt>
     void priv_range_insert(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
     {
        if(first != last){        
           const size_type n = std::distance(first, last);
           containers_detail::advanced_insert_aux_proxy<T, FwdIt, T*> proxy(first, last);
           priv_range_insert(pos.get_ptr(), n, proxy);
        }
     }
  
     template <class InIt>
     void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag)
     {
        for(;first != last; ++first){
           this->emplace(pos, *first);
        }
     }
  
     void priv_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf)
     {
        //Check if we have enough memory or try to expand current memory
        size_type remaining = this->members_.m_capacity - this->members_.m_size;
        bool same_buffer_start;
        std::pair<pointer, bool> ret;
        size_type real_cap = this->members_.m_capacity;
  
        //Check if we already have room
        if (n <= remaining){
           same_buffer_start = true;
        }
        else{
           //There is not enough memory, allocate a new
           //buffer or expand the old one.
           size_type new_cap = this->next_capacity(n);
           ret = this->allocation_command
                 (allocate_new | expand_fwd | expand_bwd,
                    this->members_.m_size + n, new_cap, real_cap, this->members_.m_start);
  
           //Check for forward expansion
           same_buffer_start = ret.second && this->members_.m_start == ret.first;
           if(same_buffer_start){
              this->members_.m_capacity  = real_cap;
           }
        }
        
        //If we had room or we have expanded forward
        if (same_buffer_start){
           #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
           ++this->num_expand_fwd;
           #endif
           this->priv_range_insert_expand_forward
              (containers_detail::get_pointer(pos), n, interf);
        }
        //Backwards (and possibly forward) expansion
        else if(ret.second){
           #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
           ++this->num_expand_bwd;
           #endif
           this->priv_range_insert_expand_backwards
              ( containers_detail::get_pointer(ret.first)
              , real_cap
              , containers_detail::get_pointer(pos)
              , n
              , interf);
        }
        //New buffer
        else{
           #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
           ++this->num_alloc;
           #endif
           this->priv_range_insert_new_allocation
              ( containers_detail::get_pointer(ret.first)
              , real_cap
              , containers_detail::get_pointer(pos)
              , n
              , interf);
        }
     }
  
     void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf)
     {
        //n can't be 0, because there is nothing to do in that case
        if(!n) return;
        //There is enough memory
        T* old_finish = containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size;
        const size_type elems_after = old_finish - pos;
  
        if (elems_after > n){
           //New elements can be just copied.
           //Move to uninitialized memory last objects
           ::boost::uninitialized_move(old_finish - n, old_finish, old_finish);
           this->members_.m_size += n;
           //Copy previous to last objects to the initialized end
           boost::move_backward(pos, old_finish - n, old_finish);
           //Insert new objects in the pos
           interf.copy_all_to(pos);
        }
        else {
           //The new elements don't fit in the [pos, end()) range. Copy
           //to the beginning of the unallocated zone the last new elements.
           interf.uninitialized_copy_some_and_update(old_finish, elems_after, false);
           this->members_.m_size += n - elems_after;
           //Copy old [pos, end()) elements to the uninitialized memory
           ::boost::uninitialized_move
              ( pos, old_finish, containers_detail::get_pointer(this->members_.m_start) + this->members_.m_size);
           this->members_.m_size += elems_after;
           //Copy first new elements in pos
           interf.copy_all_to(pos);
        }
     }
  
     void priv_range_insert_new_allocation
        (T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf)
     {
        //n can be zero, if we want to reallocate!
        T *new_finish = new_start;
        T *old_finish;
        //Anti-exception rollbacks
        typename value_traits::ArrayDeallocator scoped_alloc(new_start, this->alloc(), new_cap);
        typename value_traits::ArrayDestructor constructed_values_destroyer(new_start, 0u);
  
        //Initialize with [begin(), pos) old buffer 
        //the start of the new buffer
        T *old_buffer = containers_detail::get_pointer(this->members_.m_start);
        if(old_buffer){
           new_finish = ::boost::uninitialized_move
              (containers_detail::get_pointer(this->members_.m_start), pos, old_finish = new_finish);
           constructed_values_destroyer.increment_size(new_finish - old_finish);
        }
        //Initialize new objects, starting from previous point
        interf.uninitialized_copy_all_to(old_finish = new_finish);
        new_finish += n;
        constructed_values_destroyer.increment_size(new_finish - old_finish);
        //Initialize from the rest of the old buffer, 
        //starting from previous point
        if(old_buffer){
           new_finish = ::boost::uninitialized_move
              (pos, old_buffer + this->members_.m_size, new_finish);
           //Destroy and deallocate old elements
           //If there is allocated memory, destroy and deallocate
           if(!value_traits::trivial_dctr_after_move)
              this->destroy_n(old_buffer, this->members_.m_size); 
           this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
        }
        this->members_.m_start     = new_start;
        this->members_.m_size      = new_finish - new_start;
        this->members_.m_capacity  = new_cap;
        //All construction successful, disable rollbacks
        constructed_values_destroyer.release();
        scoped_alloc.release();
     }
  
     void priv_range_insert_expand_backwards
           (T* new_start, size_type new_capacity,
            T* pos, const size_type n, advanced_insert_aux_int_t &interf)
     {
        //n can be zero to just expand capacity
        //Backup old data
        T* old_start  = containers_detail::get_pointer(this->members_.m_start);
        T* old_finish = old_start + this->members_.m_size;
        size_type old_size = this->members_.m_size;
  
        //We can have 8 possibilities:
        const size_type elemsbefore   = (size_type)(pos - old_start);
        const size_type s_before      = (size_type)(old_start - new_start);
  
        //Update the vector buffer information to a safe state
        this->members_.m_start      = new_start;
        this->members_.m_capacity   = new_capacity;
        this->members_.m_size = 0;
  
        //If anything goes wrong, this object will destroy
        //all the old objects to fulfill previous vector state
        typename value_traits::OldArrayDestructor old_values_destroyer(old_start, old_size);
        //Check if s_before is big enough to hold the beginning of old data + new data
        if(difference_type(s_before) >= difference_type(elemsbefore + n)){
           //Copy first old values before pos, after that the new objects
           ::boost::uninitialized_move(old_start, pos, new_start);
           this->members_.m_size = elemsbefore;
           interf.uninitialized_copy_all_to(new_start + elemsbefore);
           this->members_.m_size += n;
           //Check if s_before is so big that even copying the old data + new data
           //there is a gap between the new data and the old data
           if(s_before >= (old_size + n)){
              //Old situation:
              // _________________________________________________________
              //|            raw_mem                | old_begin | old_end |
              //| __________________________________|___________|_________|
              //
              //New situation:
              // _________________________________________________________
              //| old_begin |    new   | old_end |         raw_mem        |
              //|___________|__________|_________|________________________|
              //
              //Now initialize the rest of memory with the last old values
              ::boost::uninitialized_move
                 (pos, old_finish, new_start + elemsbefore + n);
              //All new elements correctly constructed, avoid new element destruction
              this->members_.m_size = old_size + n;
              //Old values destroyed automatically with "old_values_destroyer"
              //when "old_values_destroyer" goes out of scope unless the have trivial
              //destructor after move.
              if(value_traits::trivial_dctr_after_move)
                 old_values_destroyer.release();
           }
           //s_before is so big that divides old_end
           else{
              //Old situation:
              // __________________________________________________
              //|            raw_mem         | old_begin | old_end |
              //| ___________________________|___________|_________|
              //
              //New situation:
              // __________________________________________________
              //| old_begin |   new    | old_end |  raw_mem        |
              //|___________|__________|_________|_________________|
              //
              //Now initialize the rest of memory with the last old values
              //All new elements correctly constructed, avoid new element destruction
              size_type raw_gap = s_before - (elemsbefore + n);
              //Now initialize the rest of s_before memory with the
              //first of elements after new values
              ::boost::uninitialized_move(pos, pos + raw_gap, new_start + elemsbefore + n);
              //Update size since we have a contiguous buffer
              this->members_.m_size = old_size + s_before;
              //All new elements correctly constructed, avoid old element destruction
              old_values_destroyer.release();
              //Now copy remaining last objects in the old buffer begin
              T *to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start);
              //Now destroy redundant elements except if they were moved and
              //they have trivial destructor after move
              size_type n_destroy =  old_finish - to_destroy;
              if(!value_traits::trivial_dctr_after_move)
                 this->destroy_n(to_destroy, n_destroy);
              this->members_.m_size -= n_destroy;
           }
        }
        else{
           //Check if we have to do the insertion in two phases
           //since maybe s_before is not big enough and
           //the buffer was expanded both sides
           //
           //Old situation:
           // _________________________________________________
           //| raw_mem | old_begin + old_end |  raw_mem        |
           //|_________|_____________________|_________________|
           //
           //New situation with do_after:
           // _________________________________________________
           //|     old_begin + new + old_end     |  raw_mem    |
           //|___________________________________|_____________|
           //
           //New without do_after:
           // _________________________________________________
           //| old_begin + new + old_end  |  raw_mem           |
           //|____________________________|____________________|
           //
           bool do_after    = n > s_before;
  
           //Now we can have two situations: the raw_mem of the
           //beginning divides the old_begin, or the new elements:
           if (s_before <= elemsbefore) {
              //The raw memory divides the old_begin group:
              //
              //If we need two phase construction (do_after)
              //new group is divided in new = new_beg + new_end groups
              //In this phase only new_beg will be inserted
              //
              //Old situation:
              // _________________________________________________
              //| raw_mem | old_begin | old_end |  raw_mem        |
              //|_________|___________|_________|_________________|
              //
              //New situation with do_after(1):
              //This is not definitive situation, the second phase
              //will include
              // _________________________________________________
              //| old_begin | new_beg | old_end |  raw_mem        |
              //|___________|_________|_________|_________________|
              //
              //New situation without do_after:
              // _________________________________________________
              //| old_begin | new | old_end |  raw_mem            |
              //|___________|_____|_________|_____________________|
              //
              //Copy the first part of old_begin to raw_mem
              T *start_n = old_start + difference_type(s_before); 
              ::boost::uninitialized_move(old_start, start_n, new_start);
              //The buffer is all constructed until old_end,
              //release destroyer and update size
              old_values_destroyer.release();
              this->members_.m_size = old_size + s_before;
              //Now copy the second part of old_begin overwriting himself
              T* next = ::boost::move(start_n, pos, old_start);
              if(do_after){
                 //Now copy the new_beg elements
                 interf.copy_some_and_update(next, s_before, true);
              }
              else{
                 //Now copy the all the new elements
                 interf.copy_all_to(next);
                 T* move_start = next + n;
                 //Now displace old_end elements
                 T* move_end   = ::boost::move(pos, old_finish, move_start);
                 //Destroy remaining moved elements from old_end except if
                 //they have trivial destructor after being moved
                 difference_type n_destroy = s_before - n;
                 if(!value_traits::trivial_dctr_after_move)
                    this->destroy_n(move_end, n_destroy);
                 this->members_.m_size -= n_destroy;
              }
           }
           else {
              //If we have to expand both sides,
              //we will play if the first new values so
              //calculate the upper bound of new values
  
              //The raw memory divides the new elements
              //
              //If we need two phase construction (do_after)
              //new group is divided in new = new_beg + new_end groups
              //In this phase only new_beg will be inserted
              //
              //Old situation:
              // _______________________________________________________
              //|   raw_mem     | old_begin | old_end |  raw_mem        |
              //|_______________|___________|_________|_________________|
              //
              //New situation with do_after():
              // ____________________________________________________
              //| old_begin |    new_beg    | old_end |  raw_mem     |
              //|___________|_______________|_________|______________|
              //
              //New situation without do_after:
              // ______________________________________________________
              //| old_begin | new | old_end |  raw_mem                 |
              //|___________|_____|_________|__________________________|
              //
              //First copy whole old_begin and part of new to raw_mem
              ::boost::uninitialized_move(old_start, pos, new_start);
              this->members_.m_size = elemsbefore;
  
              const size_type mid_n = difference_type(s_before) - elemsbefore;
              interf.uninitialized_copy_some_and_update(new_start + elemsbefore, mid_n, true);
              this->members_.m_size = old_size + s_before;
              //The buffer is all constructed until old_end,
              //release destroyer and update size
              old_values_destroyer.release();
  
              if(do_after){
                 //Copy new_beg part
                 interf.copy_some_and_update(old_start, s_before - mid_n, true);
              }
              else{
                 //Copy all new elements
                 interf.copy_all_to(old_start);
                 T* move_start = old_start + (n-mid_n);
                 //Displace old_end
                 T* move_end = ::boost::move(pos, old_finish, move_start);
                 //Destroy remaining moved elements from old_end except if they
                 //have trivial destructor after being moved
                 difference_type n_destroy = s_before - n;
                 if(!value_traits::trivial_dctr_after_move)
                    this->destroy_n(move_end, n_destroy);
                 this->members_.m_size -= n_destroy;
              }
           }
  
           //This is only executed if two phase construction is needed
           //This can be executed without exception handling since we
           //have to just copy and append in raw memory and
           //old_values_destroyer has been released in phase 1.
           if(do_after){
              //The raw memory divides the new elements
              //
              //Old situation:
              // ______________________________________________________
              //|   raw_mem    | old_begin |  old_end   |  raw_mem     |
              //|______________|___________|____________|______________|
              //
              //New situation with do_after(1):
              // _______________________________________________________
              //| old_begin   +   new_beg  | new_end |old_end | raw_mem |
              //|__________________________|_________|________|_________|
              //
              //New situation with do_after(2):
              // ______________________________________________________
              //| old_begin      +       new            | old_end |raw |
              //|_______________________________________|_________|____|
              //
              const size_type n_after  = n - s_before;
              const difference_type elemsafter = old_size - elemsbefore;
  
              //We can have two situations:
              if (elemsafter > difference_type(n_after)){
                 //The raw_mem from end will divide displaced old_end
                 //
                 //Old situation:
                 // ______________________________________________________
                 //|   raw_mem    | old_begin |  old_end   |  raw_mem     |
                 //|______________|___________|____________|______________|
                 //
                 //New situation with do_after(1):
                 // _______________________________________________________
                 //| old_begin   +   new_beg  | new_end |old_end | raw_mem |
                 //|__________________________|_________|________|_________|
                 //
                 //First copy the part of old_end raw_mem
                 T* finish_n = old_finish - difference_type(n_after);
                 ::boost::uninitialized_move(finish_n, old_finish, old_finish);
                 this->members_.m_size += n_after;
                 //Displace the rest of old_end to the new position
                 boost::move_backward(pos, finish_n, old_finish);
                 //Now overwrite with new_end
                 //The new_end part is [first + (n - n_after), last)
                 interf.copy_all_to(pos);
              }
              else {
                 //The raw_mem from end will divide new_end part
                 //
                 //Old situation:
                 // _____________________________________________________________
                 //|   raw_mem    | old_begin |  old_end   |  raw_mem            |
                 //|______________|___________|____________|_____________________|
                 //
                 //New situation with do_after(2):
                 // _____________________________________________________________
                 //| old_begin   +   new_beg  |     new_end   |old_end | raw_mem |
                 //|__________________________|_______________|________|_________|
                 //
                 size_type mid_last_dist = n_after - elemsafter;
                 //First initialize data in raw memory
                 //The new_end part is [first + (n - n_after), last)
                 interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
                 this->members_.m_size += mid_last_dist;
                 ::boost::uninitialized_move(pos, old_finish, old_finish + mid_last_dist);
                 this->members_.m_size += n_after - mid_last_dist;
                 //Now copy the part of new_end over constructed elements
                 interf.copy_all_to(pos);
              }
           }
        }
     }
  
     template <class InIt>
     void priv_assign_aux(InIt first, InIt last, std::input_iterator_tag)
     {
        //Overwrite all elements we can from [first, last)
        iterator cur = begin();
        for ( ; first != last && cur != end(); ++cur, ++first){
           *cur = *first;
        }
  
        if (first == last){
           //There are no more elements in the sequence, erase remaining
           this->erase(cur, cend());
        }
        else{
           //There are more elements in the range, insert the remaining ones
           this->insert(this->cend(), first, last);
        }
     }
  
     template <class FwdIt>
     void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
     {
        size_type n = std::distance(first, last);
        if(!n){
           this->prot_destroy_all();
           return;
        }
        //Check if we have enough memory or try to expand current memory
        size_type remaining = this->members_.m_capacity - this->members_.m_size;
        bool same_buffer_start;
        std::pair<pointer, bool> ret;
        size_type real_cap = this->members_.m_capacity;
  
        if (n <= remaining){
           same_buffer_start = true;
        }
        else{
           //There is not enough memory, allocate a new buffer
           size_type new_cap = this->next_capacity(n);
           ret = this->allocation_command
                 (allocate_new | expand_fwd | expand_bwd,
                    this->size() + n, new_cap, real_cap, this->members_.m_start);
           same_buffer_start = ret.second && this->members_.m_start == ret.first;
           if(same_buffer_start){
              this->members_.m_capacity  = real_cap;
           }
        }
        
        if(same_buffer_start){
           T *start = containers_detail::get_pointer(this->members_.m_start);
           if (this->size() >= n){
              //There is memory, but there are more old elements than new ones
              //Overwrite old elements with new ones
              std::copy(first, last, start);
              //Destroy remaining old elements
              this->destroy_n(start + n, this->members_.m_size - n);
              this->members_.m_size = n;
           }
           else{
              //There is memory, but there are less old elements than new ones
              //First overwrite some old elements with new ones
              FwdIt mid = first;
              std::advance(mid, this->size());
              // iG T *end = std::copy(first, mid, start);
              T *end = std::copy(first, mid, start);
              //Initialize the remaining new elements in the uninitialized memory
              // iG std::uninitialized_copy(mid, last, end);
              ::boost::uninitialized_copy_or_move(mid, last, end);
              this->members_.m_size = n;
           }
        }
        else if(!ret.second){
           typename value_traits::ArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
           // iG std::uninitialized_copy(first, last, containers_detail::get_pointer(ret.first));
           ::boost::uninitialized_copy_or_move(first, last, containers_detail::get_pointer(ret.first));
           scoped_alloc.release();
           //Destroy and deallocate old buffer
           if(this->members_.m_start != 0){
              this->destroy_n(containers_detail::get_pointer(this->members_.m_start), this->members_.m_size); 
              this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
           }
           this->members_.m_start     = ret.first;
           this->members_.m_size      = n;
           this->members_.m_capacity  = real_cap;
        }
        else{
           //Backwards expansion
           //If anything goes wrong, this object will destroy old objects
           T *old_start         = containers_detail::get_pointer(this->members_.m_start);
           size_type old_size   = this->members_.m_size;
           typename value_traits::OldArrayDestructor old_values_destroyer(old_start, old_size);
           //If something goes wrong size will be 0
           //but holding the whole buffer
           this->members_.m_size  = 0;
           this->members_.m_start = ret.first;
           this->members_.m_capacity = real_cap;
           
           //Backup old buffer data
           size_type old_offset    = old_start - containers_detail::get_pointer(ret.first);
           size_type first_count   = containers_detail::min_value(n, old_offset);
  
           FwdIt mid = first;
           std::advance(mid, first_count);
           // iG std::uninitialized_copy(first, mid, containers_detail::get_pointer(ret.first));
           ::boost::uninitialized_copy_or_move(first, mid, containers_detail::get_pointer(ret.first));
  
           if(old_offset > n){
              //All old elements will be destroyed by "old_values_destroyer" 
              this->members_.m_size = n;
           }
           else{
              //We have constructed objects from the new begin until
              //the old end so release the rollback destruction
              old_values_destroyer.release();
              this->members_.m_start  = ret.first;
              this->members_.m_size   = first_count + old_size;
              //Now overwrite the old values
              size_type second_count = containers_detail::min_value(old_size, n - first_count);
              FwdIt mid2 = mid;
              std::advance(mid2, second_count);
              // iG std::copy(mid, mid2, old_start);
              std::copy(mid, mid2, old_start);
              
              //Check if we still have to append elements in the
              //uninitialized end
              if(second_count == old_size){
                 // iG std::copy(mid2, last, old_start + old_size);
                 std::copy(mid2, last, old_start + old_size);
              }
              else{
                 //We have to destroy some old values
                 this->destroy_n
                    (old_start + second_count, old_size - second_count);
                 this->members_.m_size = n;
              }
              this->members_.m_size = n;                        
           }
        }
     }
  
     template <class Integer>
     void priv_assign_dispatch(Integer n, Integer val, containers_detail::true_)
     { this->assign((size_type) n, (value_type)val); }
  
     template <class InIt>
     void priv_assign_dispatch(InIt first, InIt last, containers_detail::false_)
     { 
        //Dispatch depending on integer/iterator
        typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
        this->priv_assign_aux(first, last, ItCat()); 
     }
  
     template <class Integer>
     void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, containers_detail::true_) 
     {  this->insert(pos, (size_type)n, (T)val);  }
  
     template <class InIt>
     void priv_insert_dispatch(const_iterator pos, InIt first, 
                               InIt last,      containers_detail::false_)
     {
        //Dispatch depending on integer/iterator
        typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
        this->priv_range_insert(pos, first, last, ItCat());
     }
  
     void priv_check_range(size_type n) const 
     {
        //If n is out of range, throw an out_of_range exception
        if (n >= size())
           throw std::out_of_range("vector::at");
     }
  
     #ifdef BOOST_CONTAINERS_VECTOR_ALLOC_STATS
     public:
     unsigned int num_expand_fwd;
     unsigned int num_expand_bwd;
     unsigned int num_shrink;
     unsigned int num_alloc;
     void reset_alloc_stats()
     {  num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0;   }
     #endif
     /// @endcond
  };
  
  template <class T, class A>
  inline bool 
  operator==(const vector<T, A>& x, const vector<T, A>& y)
  {
     //Check first size and each element if needed
     return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
  }
  
  template <class T, class A>
  inline bool 
  operator!=(const vector<T, A>& x, const vector<T, A>& y)
  {
     //Check first size and each element if needed
    return x.size() != y.size() || !std::equal(x.begin(), x.end(), y.begin());
  }
  
  template <class T, class A>
  inline bool 
  operator<(const vector<T, A>& x, const vector<T, A>& y)
  {
     return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
  }
  
  template <class T, class A>
  inline void swap(vector<T, A>& x, vector<T, A>& y)
  {  x.swap(y);  }
  
  }}
  
  /// @cond
  
  namespace boost {
  
  /*
  
  //!has_trivial_destructor_after_move<> == true_type
  //!specialization for optimizations
  template <class T, class A>
  struct has_trivial_destructor_after_move<boost::container::vector<T, A> >
  {
     static const bool value = has_trivial_destructor<A>::value;
  };
  
  */
  
  }
  
  /// @endcond
  
  #include <boost/container/detail/config_end.hpp>
  
  #endif //   #ifndef  BOOST_CONTAINERS_CONTAINERS_VECTOR_HPP
  
  