Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:30:59

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Benedek Thaler 2015-2016
0004 // (C) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
0005 // Software License, Version 1.0. (See accompanying file
0006 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 // See http://www.boost.org/libs/container for documentation.
0009 //
0010 //////////////////////////////////////////////////////////////////////////////
0011 
0012 #ifndef BOOST_CONTAINER_DEVECTOR_HPP
0013 #define BOOST_CONTAINER_DEVECTOR_HPP
0014 
0015 #include <boost/container/detail/config_begin.hpp>
0016 #include <boost/container/detail/workaround.hpp>
0017 
0018 #include <cstring> // memcpy
0019 
0020 #include <boost/assert.hpp>
0021 
0022 #include <boost/container/detail/copy_move_algo.hpp>
0023 #include <boost/container/new_allocator.hpp> //new_allocator
0024 #include <boost/container/allocator_traits.hpp> //allocator_traits
0025 #include <boost/container/detail/algorithm.hpp> //equal()
0026 #include <boost/container/throw_exception.hpp>
0027 #include <boost/container/options.hpp>
0028 
0029 #include <boost/container/detail/guards_dended.hpp>
0030 #include <boost/container/detail/iterator.hpp>
0031 #include <boost/container/detail/iterators.hpp>
0032 #include <boost/container/detail/destroyers.hpp>
0033 #include <boost/container/detail/min_max.hpp>
0034 #include <boost/container/detail/next_capacity.hpp>
0035 #include <boost/container/detail/alloc_helpers.hpp>
0036 #include <boost/container/detail/advanced_insert_int.hpp>
0037 
0038 // move
0039 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0040 #include <boost/move/detail/fwd_macros.hpp>
0041 #endif
0042 #include <boost/move/detail/move_helpers.hpp>
0043 #include <boost/move/adl_move_swap.hpp>
0044 #include <boost/move/iterator.hpp>
0045 #include <boost/move/traits.hpp>
0046 #include <boost/move/utility_core.hpp>
0047 #include <boost/move/detail/to_raw_pointer.hpp>
0048 #include <boost/move/algo/detail/merge.hpp>
0049 
0050 //std
0051 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0052 #include <initializer_list>    //for std::initializer_list
0053 #endif
0054 
0055 namespace boost {
0056 namespace container {
0057 
0058 #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0059 
0060 struct growth_factor_60;
0061 
0062 template<class Options, class AllocatorSizeType>
0063 struct get_devector_opt
0064 {
0065     typedef devector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
0066                         , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
0067                         , default_if_zero<Options::free_fraction, relocate_on_90::value>::value
0068                         > type;
0069 };
0070 
0071 template<class AllocatorSizeType>
0072 struct get_devector_opt<void, AllocatorSizeType>
0073 {
0074     typedef devector_opt< growth_factor_60, AllocatorSizeType, relocate_on_90::value> type;
0075 };
0076 
0077 #endif    //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0078 
0079 struct reserve_only_tag_t {};
0080 struct reserve_uninitialized_t {};
0081 struct review_implementation_t {};
0082 
0083 //struct unsafe_uninitialized_tag_t {};
0084 
0085 /**
0086  * A vector-like sequence container providing front and back operations
0087  * (e.g: `push_front`/`pop_front`/`push_back`/`pop_back`) with amortized constant complexity.
0088  *
0089  * Models the [SequenceContainer], [ReversibleContainer], and [AllocatorAwareContainer] concepts.
0090  *
0091  * **Requires**:
0092  *   - `T` shall be [MoveInsertable] into the devector.
0093  *   - `T` shall be [Erasable] from any `devector<T, allocator_type, GP>`.
0094  *   - `GrowthFactor`, and `Allocator` must model the concepts with the same names or be void.
0095  *
0096  * **Definition**: `T` is `NothrowConstructible` if it's either nothrow move constructible or
0097  * nothrow copy constructible.
0098  *
0099  * **Definition**: `T` is `NothrowAssignable` if it's either nothrow move assignable or
0100  * nothrow copy assignable.
0101  *
0102  * **Exceptions**: The exception specifications assume `T` is nothrow [Destructible].
0103  *
0104  * Most methods providing the strong exception guarantee assume `T` either has a move
0105  * constructor marked noexcept or is [CopyInsertable] into the devector. If it isn't true,
0106  * and the move constructor throws, the guarantee is waived and the effects are unspecified.
0107  *
0108  * In addition to the exceptions specified in the **Throws** clause, the following operations
0109  * of `T` can throw when any of the specified concept is required:
0110  *   - [DefaultInsertable][]: Default constructor
0111  *   - [MoveInsertable][]: Move constructor
0112  *   - [CopyInsertable][]: Copy constructor
0113  *   - [DefaultConstructible][]: Default constructor
0114  *   - [EmplaceConstructible][]: Constructor selected by the given arguments
0115  *   - [MoveAssignable][]: Move assignment operator
0116  *   - [CopyAssignable][]: Copy assignment operator
0117  *
0118  * Furthermore, not `noexcept` methods throws whatever the allocator throws
0119  * if memory allocation fails. Such methods also throw `length_error` if the capacity
0120  * exceeds `max_size()`.
0121  *
0122  * **Remark**: If a method invalidates some iterators, it also invalidates references
0123  * and pointers to the elements pointed by the invalidated iterators.
0124  *
0125  *! \tparam Options A type produced from \c boost::container::devector_options.
0126  *
0127  * [SequenceContainer]: http://en.cppreference.com/w/cpp/concept/SequenceContainer
0128  * [ReversibleContainer]: http://en.cppreference.com/w/cpp/concept/ReversibleContainer
0129  * [AllocatorAwareContainer]: http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer
0130  * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
0131  * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
0132  * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0133  * [Erasable]: http://en.cppreference.com/w/cpp/concept/Erasable
0134  * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
0135  * [Destructible]: http://en.cppreference.com/w/cpp/concept/Destructible
0136  * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
0137  * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
0138  * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
0139  */
0140 template < typename T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void)>
0141 class devector
0142 {
0143    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0144    typedef boost::container::allocator_traits
0145       <typename real_allocator<T, A>::type>                                      allocator_traits_type;
0146    typedef typename allocator_traits_type::size_type                             alloc_size_type;
0147    typedef typename get_devector_opt<Options, alloc_size_type>::type             options_type;
0148    typedef typename options_type::growth_factor_type                             growth_factor_type;
0149    typedef typename options_type::stored_size_type                               stored_size_type;
0150    BOOST_STATIC_CONSTEXPR std::size_t devector_min_free_fraction =
0151       options_type::free_fraction;
0152 
0153    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0154 
0155    public:
0156    // Standard Interface Types:
0157    typedef T                                                                     value_type;
0158    typedef BOOST_CONTAINER_IMPDEF
0159       (typename real_allocator<T BOOST_MOVE_I A>::type)                          allocator_type;
0160    typedef allocator_type                                                        stored_allocator_type;
0161    typedef typename    allocator_traits<allocator_type>::pointer                 pointer;
0162    typedef typename    allocator_traits<allocator_type>::const_pointer           const_pointer;
0163    typedef typename    allocator_traits<allocator_type>::reference               reference;
0164    typedef typename    allocator_traits<allocator_type>::const_reference         const_reference;
0165    typedef typename    allocator_traits<allocator_type>::size_type               size_type;
0166    typedef typename    allocator_traits<allocator_type>::difference_type         difference_type;
0167    typedef pointer                                                               iterator;
0168    typedef const_pointer                                                         const_iterator;
0169    typedef BOOST_CONTAINER_IMPDEF
0170       (boost::container::reverse_iterator<iterator>)                             reverse_iterator;
0171    typedef BOOST_CONTAINER_IMPDEF
0172       (boost::container::reverse_iterator<const_iterator>)                       const_reverse_iterator;
0173 
0174    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0175    private:
0176 
0177    //`allocator_type::value_type` must match container's `value type`. If this
0178    //assertion fails, please review your allocator definition. 
0179    BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<value_type, typename allocator_traits<allocator_type>::value_type>::value));
0180 
0181    BOOST_COPYABLE_AND_MOVABLE(devector)
0182 
0183    // Guard to deallocate buffer on exception
0184    typedef typename detail::allocation_guard<allocator_type> allocation_guard;
0185 
0186    // Random access pseudo iterator always yielding to the same result
0187    typedef constant_iterator<T> cvalue_iterator;
0188 
0189    static size_type to_internal_capacity(size_type desired_capacity)
0190    {
0191       const size_type rounder = devector_min_free_fraction - 2u;
0192       const size_type divisor = devector_min_free_fraction - 1u;
0193       size_type const nc = ((desired_capacity + rounder) / divisor) * devector_min_free_fraction;
0194       BOOST_ASSERT(desired_capacity <= (nc - nc / devector_min_free_fraction));
0195       return nc;
0196    }
0197 
0198    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0199 
0200    // Standard Interface
0201    public:
0202    // construct/copy/destroy
0203 
0204    /**
0205    * **Effects**: Constructs an empty devector.
0206    *
0207    * **Postcondition**: `empty() && front_free_capacity() == 0
0208    * && back_free_capacity() == 0`.
0209    *
0210    * **Complexity**: Constant.
0211    */
0212    devector() BOOST_NOEXCEPT
0213       : m_()
0214    {}
0215 
0216    /**
0217    * **Effects**: Constructs an empty devector, using the specified allocator.
0218    *
0219    * **Postcondition**: `empty() && front_free_capacity() == 0
0220    * && back_free_capacity() == 0`.
0221    *
0222    * **Complexity**: Constant.
0223    */
0224    explicit devector(const allocator_type& allocator) BOOST_NOEXCEPT
0225       : m_(allocator)
0226    {}
0227 
0228    /**
0229    * **Effects**: Constructs an empty devector, using the specified allocator
0230    * and reserves `n` slots as if `reserve(n)` was called.
0231    *
0232    * **Postcondition**: `empty() && capacity() >= n`.
0233    *
0234    * **Exceptions**: Strong exception guarantee.
0235    *
0236    * **Complexity**: Constant.
0237    */
0238    devector(size_type n, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
0239       : m_(reserve_only_tag_t(), allocator, to_internal_capacity(n))
0240    {}
0241 
0242    /**
0243    * **Effects**: Constructs an empty devector, using the specified allocator
0244    * and reserves at least `front_free_cap + back_free_cap` slots as if `reserve_front(front_cap)` and
0245    * `reserve_back(back_cap)` was called.
0246    *
0247    * **Postcondition**: `empty() && front_free_capacity() >= front_free_cap
0248    * && back_free_capacity() >= back_free_cap`.
0249    *
0250    * **Exceptions**: Strong exception guarantee.
0251    *
0252    * **Complexity**: Constant.
0253    */
0254    devector(size_type front_free_cap, size_type back_free_cap, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
0255       : m_(reserve_only_tag_t(), allocator, front_free_cap, back_free_cap)
0256    {}
0257 
0258    /**
0259    * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
0260    *
0261    * **Effects**: Constructs a devector with `n` value_initialized elements using the specified allocator.
0262    *
0263    * **Requires**: `T` shall be [DefaultInsertable] into `*this`.
0264    *
0265    * **Postcondition**: `size() == n`.
0266    *
0267    * **Exceptions**: Strong exception guarantee.
0268    *
0269    * **Complexity**: Linear in `n`.
0270    */
0271    explicit devector(size_type n, const allocator_type& allocator = allocator_type())
0272       : m_(reserve_uninitialized_t(), allocator, n)
0273    {
0274       allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
0275       boost::container::uninitialized_value_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin());
0276       buffer_guard.release();
0277       BOOST_ASSERT(invariants_ok());
0278    }
0279 
0280    /**
0281    * **Effects**: Constructs a devector with `n` default-initialized elements using the specified allocator.
0282    *
0283    * **Requires**: `T` shall be [DefaultInsertable] into `*this`.
0284    *
0285    * **Postcondition**: `size() == n`.
0286    *
0287    * **Exceptions**: Strong exception guarantee.
0288    *
0289    * **Complexity**: Linear in `n`.
0290    */
0291    explicit devector(size_type n, default_init_t, const allocator_type& allocator = allocator_type())
0292       : m_(reserve_uninitialized_t(), allocator, n)
0293    {
0294       allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
0295       boost::container::uninitialized_default_init_alloc_n(get_allocator_ref(), n, this->priv_raw_begin());
0296       buffer_guard.release();
0297       BOOST_ASSERT(invariants_ok());
0298    }
0299 
0300    /**
0301    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0302    *
0303    * **Effects**: Constructs a devector with `n` copies of `value`, using the specified allocator.
0304    *
0305    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
0306    *
0307    * **Postcondition**: `size() == n`.
0308    *
0309    * **Exceptions**: Strong exception guarantee.
0310    *
0311    * **Complexity**: Linear in `n`.
0312    */
0313    devector(size_type n, const T& value, const allocator_type& allocator = allocator_type())
0314       : m_(reserve_uninitialized_t(), allocator, n)
0315    {
0316       construct_from_range(cvalue_iterator(value, n), cvalue_iterator());
0317       BOOST_ASSERT(invariants_ok());
0318    }
0319 
0320    /**
0321    * **Effects**: Constructs a devector equal to the range `[first,last)`, using the specified allocator.
0322    *
0323    * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified
0324    * iterator does not meet the forward iterator requirements, `T` shall also be [MoveInsertable]
0325    * into `*this`.
0326    *
0327    * **Postcondition**: `size() == boost::container::iterator_distance(first, last)
0328    *
0329    * **Exceptions**: Strong exception guarantee.
0330    *
0331    * **Complexity**: Makes only `N` calls to the copy constructor of `T` (where `N` is the distance between `first`
0332    * and `last`), at most one allocation and no reallocations if iterators first and last are of forward,
0333    * bidirectional, or random access categories. It makes `O(N)` calls to the copy constructor of `T`
0334    * and `O(log(N)) reallocations if they are just input iterators.
0335    *
0336    * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
0337    * unless an exception is thrown.
0338    *
0339    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
0340    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
0341    */
0342    template <class InputIterator>
0343    devector(InputIterator first, InputIterator last, const allocator_type& allocator = allocator_type()
0344       //Input iterators
0345       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
0346             < void
0347             BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
0348             BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
0349             >::type * = 0)
0350       )
0351       : m_(allocator)
0352    {
0353       BOOST_CONTAINER_TRY{
0354          while (first != last) {
0355             this->emplace_back(*first++);
0356          }
0357          BOOST_ASSERT(invariants_ok());
0358       }
0359       BOOST_CONTAINER_CATCH(...){
0360          this->destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
0361          this->deallocate_buffer();
0362       }
0363       BOOST_CONTAINER_CATCH_END
0364    }
0365 
0366    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0367 
0368    template <class ForwardIterator>
0369    devector(ForwardIterator first, ForwardIterator last, const allocator_type& allocator = allocator_type()
0370       //Other iterators
0371       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
0372             < void
0373             BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
0374             BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
0375             >::type * = 0)
0376       )
0377       : m_(reserve_uninitialized_t(), allocator, boost::container::iterator_udistance(first, last))
0378    {
0379       this->construct_from_range(first, last);
0380       BOOST_ASSERT(invariants_ok());
0381    }
0382 
0383    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0384 
0385    /**
0386    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0387    *
0388    * **Effects**: Copy constructs a devector.
0389    *
0390    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
0391    *
0392    * **Postcondition**: `this->size() == x.size()`.
0393    *
0394    * **Exceptions**: Strong exception guarantee.
0395    *
0396    * **Complexity**: Linear in the size of `x`.
0397    */
0398    devector(const devector& x)
0399       : m_(reserve_uninitialized_t(), allocator_traits_type::select_on_container_copy_construction(x.get_allocator_ref()), x.size())
0400    {
0401       this->construct_from_range(x.begin(), x.end());
0402       BOOST_ASSERT(invariants_ok());
0403    }
0404 
0405    /**
0406    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0407    *
0408    * **Effects**: Copy constructs a devector, using the specified allocator.
0409    *
0410    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
0411    *
0412    * **Postcondition**: `*this == x`.
0413    *
0414    * **Exceptions**: Strong exception guarantee.
0415    *
0416    * **Complexity**: Linear in the size of `x`.
0417    */
0418    devector(const devector& x, const allocator_type& allocator)
0419       : m_(reserve_uninitialized_t(), allocator, x.size())
0420    {
0421       this->construct_from_range(x.begin(), x.end());
0422       BOOST_ASSERT(invariants_ok());
0423    }
0424 
0425    /**
0426    * **Effects**: Moves `rhs`'s resources to `*this`.
0427    *
0428    * **Throws**: Nothing.
0429    *
0430    * **Postcondition**: *this has the same value `rhs` had before the operation.
0431    *                    `rhs` is left in an unspecified but valid state.
0432    *
0433    * **Exceptions**: Strong exception guarantee if not `noexcept`.
0434    *
0435    * **Complexity**: Constant.
0436    */
0437    devector(BOOST_RV_REF(devector) rhs) BOOST_NOEXCEPT_OR_NOTHROW
0438       : m_(::boost::move(rhs.m_))
0439    {
0440       BOOST_ASSERT(      invariants_ok());
0441       BOOST_ASSERT(rhs.invariants_ok());
0442    }
0443 
0444    /**
0445    * **Effects**: Moves `rhs`'s resources to `*this`, using the specified allocator.
0446    *
0447    * **Throws**: If allocation or T's move constructor throws.
0448    *
0449    * **Postcondition**: *this has the same value `rhs` had before the operation.
0450    *                    `rhs` is left in an unspecified but valid state.
0451    *
0452    * **Exceptions**: Strong exception guarantee if not `noexcept`.
0453    *
0454    * **Complexity**: Linear if allocator != rhs.get_allocator(), otherwise constant.
0455    */
0456    devector(BOOST_RV_REF(devector) rhs, const allocator_type& allocator)
0457       : m_(review_implementation_t(), allocator, rhs.m_.buffer, rhs.m_.front_idx, rhs.m_.back_idx, rhs.m_.capacity)
0458    {
0459       // TODO should move elems-by-elems if the two allocators differ
0460       // buffer is already acquired, reset rhs
0461       rhs.m_.capacity = 0u;
0462       rhs.m_.buffer = pointer();
0463       rhs.m_.front_idx = 0;
0464       rhs.m_.back_idx = 0;
0465       BOOST_ASSERT(      invariants_ok());
0466       BOOST_ASSERT(rhs.invariants_ok());
0467    }
0468 
0469    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0470    /**
0471    * **Equivalent to**: `devector(il.begin(), il.end(), allocator)`.
0472    */
0473    devector(const std::initializer_list<T>& il, const allocator_type& allocator = allocator_type())
0474       : m_(reserve_uninitialized_t(), allocator, il.size())
0475    {
0476       this->construct_from_range(il.begin(), il.end());
0477       BOOST_ASSERT(invariants_ok());
0478    }
0479    #endif
0480 
0481 /**
0482    * **Effects**: Destroys the devector. All stored values are destroyed and
0483    * used memory, if any, deallocated.
0484    *
0485    * **Complexity**: Linear in the size of `*this`.
0486    */
0487 ~devector() BOOST_NOEXCEPT
0488 {
0489    destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
0490    deallocate_buffer();
0491 }
0492 
0493 /**
0494    * **Effects**: Copies elements of `x` to `*this`. Previously
0495    * held elements get copy assigned to or destroyed.
0496    *
0497    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
0498    *
0499    * **Postcondition**: `this->size() == x.size()`, the elements of
0500    * `*this` are copies of elements in `x` in the same order.
0501    *
0502    * **Returns**: `*this`.
0503    *
0504    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
0505    * and the allocator is allowed to be propagated
0506    * ([propagate_on_container_copy_assignment] is true),
0507    * Basic exception guarantee otherwise.
0508    *
0509    * **Complexity**: Linear in the size of `x` and `*this`.
0510    *
0511    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0512    * [propagate_on_container_copy_assignment]: http://en.cppreference.com/w/cpp/memory/allocator_traits
0513    */
0514 
0515    inline devector& operator=(BOOST_COPY_ASSIGN_REF(devector) rhs)
0516    {
0517       const devector &x = rhs;
0518       if (this == &x) { return *this; } // skip self
0519 
0520       const bool do_propagate = allocator_traits_type::propagate_on_container_copy_assignment::value;
0521       BOOST_IF_CONSTEXPR(do_propagate)
0522       {
0523          allocator_type &this_alloc = this->get_allocator_ref();
0524          const allocator_type &other_alloc = x.get_allocator_ref();
0525          if (this_alloc != other_alloc)
0526          {
0527             // new allocator cannot free existing storage
0528             this->clear();
0529             this->deallocate_buffer();
0530             m_.capacity = 0u;
0531             m_.buffer = pointer();
0532          }
0533          dtl::bool_<do_propagate> flag;
0534          dtl::assign_alloc(this_alloc, other_alloc, flag);
0535       }
0536 
0537       size_type n = x.size();
0538       if (m_.capacity >= n)
0539       {
0540             this->overwrite_buffer(x.begin(), x.end());
0541       }
0542       else
0543       {
0544             this->allocate_and_copy_range(x.begin(), x.end());
0545       }
0546 
0547       BOOST_ASSERT(invariants_ok());
0548 
0549       return *this;
0550    }
0551 
0552    /**
0553    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
0554    *
0555    * **Effects**: Moves elements of `x` to `*this`. Previously
0556    * held elements get move/copy assigned to or destroyed.
0557    *
0558    * **Requires**: `T` shall be [MoveInsertable] into `*this`.
0559    *
0560    * **Postcondition**: `x` is left in an unspecified but valid state.
0561    *
0562    * **Returns**: `*this`.
0563    *
0564    * **Exceptions**: Basic exception guarantee if not `noexcept`.
0565    *
0566    * **Complexity**: Constant if allocator_traits_type::
0567    *   propagate_on_container_move_assignment is true or
0568    *   this->get>allocator() == x.get_allocator(). Linear otherwise.
0569    */
0570    devector& operator=(BOOST_RV_REF(devector) x)
0571       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
0572                                  || allocator_traits_type::is_always_equal::value)
0573    {
0574       if (BOOST_LIKELY(this != &x)) {
0575          //We know resources can be transferred at comiple time if both allocators are
0576          //always equal or the allocator is going to be propagated
0577          const bool can_steal_resources_alloc
0578             = allocator_traits_type::propagate_on_container_move_assignment::value
0579             || allocator_traits_type::is_always_equal::value;
0580          dtl::bool_<can_steal_resources_alloc> flag;
0581          this->priv_move_assign(boost::move(x), flag);
0582       }
0583       BOOST_ASSERT(invariants_ok());
0584       return *this;
0585    }
0586 
0587    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0588    /**
0589    * **Effects**: Copies elements of `il` to `*this`. Previously
0590    * held elements get copy assigned to or destroyed.
0591    *
0592    * **Requires**: `T` shall be [CopyInsertable] into `*this` and [CopyAssignable].
0593    *
0594    * **Postcondition**: `this->size() == il.size()`, the elements of
0595    * `*this` are copies of elements in `il` in the same order.
0596    *
0597    * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
0598    * from `T` and `NothrowConstructible`, Basic exception guarantee otherwise.
0599    *
0600    * **Returns**: `*this`.
0601    *
0602    * **Complexity**: Linear in the size of `il` and `*this`.
0603    *
0604    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0605    * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
0606    */
0607    inline devector& operator=(std::initializer_list<T> il)
0608    {
0609       this->assign(il.begin(), il.end());
0610       return *this;
0611    }
0612    #endif
0613 
0614    /**
0615    * **Effects**: Replaces elements of `*this` with a copy of `[first,last)`.
0616    * Previously held elements get copy assigned to or destroyed.
0617    *
0618    * **Requires**: `T` shall be [EmplaceConstructible] from `*first`. If the specified iterator
0619    * does not meet the forward iterator requirements, `T` shall be also [MoveInsertable] into `*this`.
0620    *
0621    * **Precondition**: `first` and `last` are not iterators into `*this`.
0622    *
0623    * **Postcondition**: `size() == N`, where `N` is the distance between `first` and `last`.
0624    *
0625    * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
0626    * from `*first` and `NothrowConstructible`, Basic exception guarantee otherwise.
0627    *
0628    * **Complexity**: Linear in the distance between `first` and `last`.
0629    * Makes a single reallocation at most if the iterators `first` and `last`
0630    * are of forward, bidirectional, or random access categories. It makes
0631    * `O(log(N))` reallocations if they are just input iterators.
0632    *
0633    * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
0634    * unless an exception is thrown.
0635    *
0636    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
0637    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
0638    */
0639    template <class InputIterator>
0640    void assign(InputIterator first, InputIterator last
0641       //Input iterators
0642       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
0643             < void
0644             BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
0645             BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
0646             >::type * = 0)
0647       )
0648    {
0649       first = overwrite_buffer_impl(first, last, dtl::false_());
0650       while (first != last)
0651       {
0652          this->emplace_back(*first++);
0653       }
0654    }
0655 
0656    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0657 
0658    template <class ForwardIterator>
0659    void assign(ForwardIterator first, ForwardIterator last
0660       //Other iterators
0661       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
0662             < void
0663             BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
0664             BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
0665             >::type * = 0)
0666       )
0667    {
0668       const size_type n = boost::container::iterator_udistance(first, last);
0669 
0670       if (m_.capacity >= n)
0671       {
0672          overwrite_buffer(first, last);
0673       }
0674       else
0675       {
0676          allocate_and_copy_range(first, last);
0677       }
0678 
0679       BOOST_ASSERT(invariants_ok());
0680    }
0681 
0682    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0683 
0684    /**
0685     * **Effects**: Replaces elements of `*this` with `n` copies of `u`.
0686     * Previously held elements get copy assigned to or destroyed.
0687     *
0688     * **Requires**: `T` shall be [CopyInsertable] into `*this` and
0689     * [CopyAssignable].
0690     *
0691     * **Precondition**: `u` is not a reference into `*this`.
0692     *
0693     * **Postcondition**: `size() == n` and the elements of
0694     * `*this` are copies of `u`.
0695     *
0696     * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
0697     * from `u` and `NothrowConstructible`, Basic exception guarantee otherwise.
0698     *
0699     * **Complexity**: Linear in `n` and the size of `*this`.
0700     *
0701     * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0702     * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
0703     */
0704    inline void assign(size_type n, const T& u)
0705    {
0706       cvalue_iterator first(u, n);
0707       cvalue_iterator last;
0708       this->assign(first, last);
0709    }
0710 
0711     #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0712     /** **Equivalent to**: `assign(il.begin(), il.end())`. */
0713    inline void assign(std::initializer_list<T> il)
0714     {
0715          this->assign(il.begin(), il.end());
0716     }
0717     #endif
0718 
0719    /**
0720     * **Returns**: A copy of the allocator associated with the container.
0721     *
0722     * **Complexity**: Constant.
0723     */
0724    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0725     allocator_type get_allocator() const BOOST_NOEXCEPT
0726    {
0727       return static_cast<const allocator_type&>(m_);
0728    }
0729 
0730    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0731     const allocator_type &get_stored_allocator() const BOOST_NOEXCEPT
0732    {
0733       return static_cast<const allocator_type&>(m_);
0734    }
0735 
0736    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0737          allocator_type &get_stored_allocator() BOOST_NOEXCEPT
0738    {
0739       return static_cast<allocator_type&>(m_);
0740    }
0741 
0742    // iterators
0743 
0744    /**
0745     * **Returns**: A iterator pointing to the first element in the devector,
0746     * or the past the end iterator if the devector is empty.
0747     *
0748     * **Complexity**: Constant.
0749     */
0750    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0751          iterator begin() BOOST_NOEXCEPT
0752    {
0753       return m_.buffer + m_.front_idx;
0754    }
0755 
0756    /**
0757     * **Returns**: A constant iterator pointing to the first element in the devector,
0758     * or the past the end iterator if the devector is empty.
0759     *
0760     * **Complexity**: Constant.
0761     */
0762    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0763     const_iterator begin() const BOOST_NOEXCEPT
0764    {
0765       return m_.buffer + m_.front_idx;
0766    }
0767 
0768    /**
0769     * **Returns**: An iterator pointing past the last element of the container.
0770     *
0771     * **Complexity**: Constant.
0772     */
0773    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0774          iterator end() BOOST_NOEXCEPT
0775    {
0776       return m_.buffer + m_.back_idx;
0777    }
0778 
0779    /**
0780     * **Returns**: A constant iterator pointing past the last element of the container.
0781     *
0782     * **Complexity**: Constant.
0783     */
0784    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0785     const_iterator end() const BOOST_NOEXCEPT
0786    {
0787       return m_.buffer + m_.back_idx;
0788    }
0789 
0790    /**
0791     * **Returns**: A reverse iterator pointing to the first element in the reversed devector,
0792     * or the reverse past the end iterator if the devector is empty.
0793     *
0794     * **Complexity**: Constant.
0795     */
0796    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0797     reverse_iterator rbegin() BOOST_NOEXCEPT
0798    {
0799       return reverse_iterator(m_.buffer + m_.back_idx);
0800    }
0801 
0802    /**
0803     * **Returns**: A constant reverse iterator
0804     * pointing to the first element in the reversed devector,
0805     * or the reverse past the end iterator if the devector is empty.
0806     *
0807     * **Complexity**: Constant.
0808     */
0809    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0810     const_reverse_iterator rbegin() const BOOST_NOEXCEPT
0811    {
0812       return const_reverse_iterator(m_.buffer + m_.back_idx);
0813    }
0814 
0815    /**
0816     * **Returns**: A reverse iterator pointing past the last element in the
0817     * reversed container, or to the beginning of the reversed container if it's empty.
0818     *
0819     * **Complexity**: Constant.
0820     */
0821    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0822     reverse_iterator rend() BOOST_NOEXCEPT
0823    {
0824       return reverse_iterator(m_.buffer + m_.front_idx);
0825    }
0826 
0827    /**
0828     * **Returns**: A constant reverse iterator pointing past the last element in the
0829     * reversed container, or to the beginning of the reversed container if it's empty.
0830     *
0831     * **Complexity**: Constant.
0832     */
0833    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0834     const_reverse_iterator rend() const BOOST_NOEXCEPT
0835    {
0836       return const_reverse_iterator(m_.buffer + m_.front_idx);
0837    }
0838 
0839    /**
0840     * **Returns**: A constant iterator pointing to the first element in the devector,
0841     * or the past the end iterator if the devector is empty.
0842     *
0843     * **Complexity**: Constant.
0844     */
0845    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0846     const_iterator cbegin() const BOOST_NOEXCEPT
0847    {
0848       return m_.buffer + m_.front_idx;
0849    }
0850 
0851    /**
0852     * **Returns**: A constant iterator pointing past the last element of the container.
0853     *
0854     * **Complexity**: Constant.
0855     */
0856    const_iterator cend() const BOOST_NOEXCEPT
0857    {
0858       return m_.buffer + m_.back_idx;
0859    }
0860 
0861    /**
0862     * **Returns**: A constant reverse iterator
0863     * pointing to the first element in the reversed devector,
0864     * or the reverse past the end iterator if the devector is empty.
0865     *
0866     * **Complexity**: Constant.
0867     */
0868    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0869     const_reverse_iterator crbegin() const BOOST_NOEXCEPT
0870    {
0871       return const_reverse_iterator(m_.buffer + m_.back_idx);
0872    }
0873 
0874    /**
0875     * **Returns**: A constant reverse iterator pointing past the last element in the
0876     * reversed container, or to the beginning of the reversed container if it's empty.
0877     *
0878     * **Complexity**: Constant.
0879     */
0880    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0881     const_reverse_iterator crend() const BOOST_NOEXCEPT
0882    {
0883       return const_reverse_iterator(m_.buffer + m_.front_idx);
0884    }
0885 
0886    // capacity
0887 
0888    /**
0889     * **Returns**: True, if `size() == 0`, false otherwise.
0890     *
0891     * **Complexity**: Constant.
0892     */
0893    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0894     bool empty() const BOOST_NOEXCEPT
0895    {
0896       return m_.front_idx == m_.back_idx;
0897    }
0898 
0899    /**
0900     * **Returns**: The number of elements the devector contains.
0901     *
0902     * **Complexity**: Constant.
0903     */
0904    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0905     size_type size() const BOOST_NOEXCEPT
0906    {
0907       return size_type(m_.back_idx - m_.front_idx);
0908    }
0909 
0910    /**
0911     * **Returns**: The maximum number of elements the devector could possibly hold.
0912     *
0913     * **Complexity**: Constant.
0914     */
0915    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0916     size_type max_size() const BOOST_NOEXCEPT
0917    {
0918       size_type alloc_max = allocator_traits_type::max_size(get_allocator_ref());
0919       size_type size_type_max = (size_type)-1;
0920       return (alloc_max <= size_type_max) ? size_type(alloc_max) : size_type_max;
0921    }
0922 
0923    /**
0924    * **Returns**: The *minimum* number of elements that can be inserted into devector using
0925    *   position-based insertions without requiring a reallocation. Note that, unlike in 
0926    *   typical sequence containers like `vector`, `capacity()`, `capacity()` can be smaller than `size()`.
0927    *   This can happen if a user inserts elements in a particular way (usually inserting at
0928    *   front up to front_free_capacity() and at back up to back_free_capacity()).
0929    * 
0930    * **Complexity**: Constant.
0931    */
0932    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0933    size_type capacity() const BOOST_NOEXCEPT
0934    {
0935       size_type const cap_reserve = m_.capacity/devector_min_free_fraction;
0936       return m_.capacity > cap_reserve ? (m_.capacity - cap_reserve) : 0u;
0937    }
0938 
0939    /**
0940     * **Returns**: The total number of elements that can be pushed to the front of the
0941     * devector without requiring reallocation.
0942     *
0943     * **Complexity**: Constant.
0944     */
0945    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0946    size_type front_free_capacity() const BOOST_NOEXCEPT
0947    {
0948       return m_.front_idx;
0949    }
0950 
0951    /**
0952     * **Returns**: The total number of elements that can be pushed to the back of the
0953     * devector without requiring reallocation.
0954     *
0955     * **Complexity**: Constant.
0956     */
0957    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0958     size_type back_free_capacity() const BOOST_NOEXCEPT
0959    {
0960       return size_type(m_.capacity - m_.back_idx);
0961    }
0962 
0963    /**
0964    * **Effects**: If `sz` is greater than the size of `*this`,
0965    * additional value-initialized elements are inserted. Invalidates iterators
0966    * if reallocation is needed. If `sz` is smaller than than the size of `*this`,
0967    * elements are erased from the extremes.
0968    *
0969    * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
0970    *
0971    * **Postcondition**: `sz == size()`.
0972    *
0973    * **Exceptions**: Strong exception guarantee.
0974    *
0975    * **Complexity**: Linear in the size of `*this` and `sz`.
0976    *
0977    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
0978    * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
0979    */
0980    inline void resize(size_type sz)
0981    {
0982       this->resize_back(sz);
0983    }
0984 
0985    /**
0986     * **Effects**: Same as resize(sz) but creates default-initialized
0987     * value-initialized.
0988     */
0989    inline void resize(size_type sz, default_init_t)
0990    {
0991       this->resize_back(sz, default_init);
0992    }
0993 
0994    /**
0995    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
0996    *
0997    * **Effects**: If `sz` is greater than the size of `*this`,
0998    * copies of `c` are inserted at extremes.
0999    * If `sz` is smaller than than the size of `*this`,
1000    * elements are popped from the extremes.
1001    *
1002    * **Postcondition**: `sz == size()`.
1003    *
1004    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1005    *
1006    * **Exceptions**: Strong exception guarantee.
1007    *
1008    * **Complexity**: Linear in the size of `*this` and `sz`.
1009    */
1010    inline void resize(size_type sz, const T& c)
1011    {
1012       this->resize_back(sz, c);
1013    }
1014 
1015    /**
1016     * **Effects**: If `sz` is greater than the size of `*this`,
1017     * additional value-initialized elements are inserted
1018     * to the front. Invalidates iterators if reallocation is needed.
1019     * If `sz` is smaller than than the size of `*this`,
1020     * elements are popped from the front.
1021     *
1022     * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
1023     *
1024     * **Postcondition**: `sz == size()`.
1025     *
1026     * **Exceptions**: Strong exception guarantee.
1027     *
1028     * **Complexity**: Linear in the size of `*this` and `sz`.
1029     *
1030     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1031     * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
1032     */
1033    inline void resize_front(size_type sz)
1034    {
1035       resize_front_impl(sz);
1036       BOOST_ASSERT(invariants_ok());
1037    }
1038 
1039    /**
1040     * **Effects**: If `sz` is greater than the size of `*this`,
1041     * additional value-initialized elements are inserted
1042     * to the front. Invalidates iterators if reallocation is needed.
1043     * If `sz` is smaller than than the size of `*this`,
1044     * elements are popped from the front.
1045     *
1046     * **Requires**: T shall be [MoveInsertable] into *this and default_initializable.
1047     *
1048     * **Postcondition**: `sz == size()`.
1049     *
1050     * **Exceptions**: Strong exception guarantee.
1051     *
1052     * **Complexity**: Linear in the size of `*this` and `sz`.
1053     *
1054     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1055     */
1056    inline void resize_front(size_type sz, default_init_t)
1057    {
1058       resize_front_impl(sz, default_init);
1059       BOOST_ASSERT(invariants_ok());
1060    }
1061 
1062    /**
1063     * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1064     *
1065     * **Effects**: If `sz` is greater than the size of `*this`,
1066     * copies of `c` are inserted to the front.
1067     * Invalidates iterators if reallocation is needed.
1068     * If `sz` is smaller than than the size of `*this`,
1069     * elements are popped from the front.
1070     *
1071     * **Postcondition**: `sz == size()`.
1072     *
1073     * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1074     *
1075     * **Exceptions**: Strong exception guarantee.
1076     *
1077     * **Complexity**: Linear in the size of `*this` and `sz`.
1078     */
1079    inline void resize_front(size_type sz, const T& c)
1080    {
1081       resize_front_impl(sz, c);
1082       BOOST_ASSERT(invariants_ok());
1083    }
1084 
1085    /**
1086     * **Effects**: If `sz` is greater than the size of `*this`,
1087     * additional value-initialized elements are inserted
1088     * to the back. Invalidates iterators if reallocation is needed.
1089     * If `sz` is smaller than than the size of `*this`,
1090     * elements are popped from the back.
1091     *
1092     * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
1093     *
1094     * **Postcondition**: `sz == size()`.
1095     *
1096     * **Exceptions**: Strong exception guarantee.
1097     *
1098     * **Complexity**: Linear in the size of `*this` and `sz`.
1099     *
1100     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1101     * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
1102     */
1103    inline void resize_back(size_type sz)
1104    {
1105       resize_back_impl(sz);
1106       BOOST_ASSERT(invariants_ok());
1107    }
1108 
1109    /**
1110     * **Effects**: If `sz` is greater than the size of `*this`,
1111     * additional value-initialized elements are inserted
1112     * to the back. Invalidates iterators if reallocation is needed.
1113     * If `sz` is smaller than than the size of `*this`,
1114     * elements are popped from the back.
1115     *
1116     * **Requires**: T shall be [MoveInsertable] into *this and default initializable.
1117     *
1118     * **Postcondition**: `sz == size()`.
1119     *
1120     * **Exceptions**: Strong exception guarantee.
1121     *
1122     * **Complexity**: Linear in the size of `*this` and `sz`.
1123     *
1124     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1125     */
1126    inline void resize_back(size_type sz, default_init_t)
1127    {
1128       resize_back_impl(sz, default_init);
1129       BOOST_ASSERT(invariants_ok());
1130    }
1131 
1132    /**
1133     * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1134     *
1135     * **Effects**: If `sz` is greater than the size of `*this`,
1136     * copies of `c` are inserted to the back.
1137     * If `sz` is smaller than than the size of `*this`,
1138     * elements are popped from the back.
1139     *
1140     * **Postcondition**: `sz == size()`.
1141     *
1142     * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1143     *
1144     * **Exceptions**: Strong exception guarantee.
1145     *
1146     * **Complexity**: Linear in the size of `*this` and `sz`.
1147     */
1148    inline void resize_back(size_type sz, const T& c)
1149    {
1150       resize_back_impl(sz, c);
1151       BOOST_ASSERT(invariants_ok());
1152    }
1153 
1154    /**
1155     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1156     *
1157     * **Effects**: Ensures that at least `n` elements can be inserted
1158     * without requiring reallocation, where `n` is `new_capacity - size()`,
1159     * if `n` is positive. Otherwise, there are no effects.
1160     * Invalidates iterators if reallocation is needed.
1161     *
1162     * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1163     *
1164     * **Complexity**: Linear in the size of *this.
1165     *
1166     * **Exceptions**: Strong exception guarantee.
1167     *
1168     * **Throws**: length_error if `new_capacity > max_size()`.
1169     */
1170    inline void reserve(size_type new_capacity)
1171    {
1172       if (this->capacity() < new_capacity) {
1173          const size_type rounder = devector_min_free_fraction - 2u;
1174          const size_type divisor = devector_min_free_fraction - 1u;
1175          size_type const nc = ((new_capacity + rounder)/divisor)*devector_min_free_fraction;
1176          BOOST_ASSERT(new_capacity <= (nc - nc / devector_min_free_fraction));
1177          size_type const sz = this->size();
1178          reallocate_at(nc, (nc-sz)/2u);
1179       }
1180       BOOST_ASSERT(invariants_ok());
1181    }
1182 
1183    /**
1184     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1185     *
1186     * **Effects**: Ensures that `n` elements can be pushed to the front
1187     * without requiring reallocation, where `n` is `new_capacity - size()`,
1188     * if `n` is positive. Otherwise, there are no effects.
1189     * Invalidates iterators if reallocation is needed.
1190     *
1191     * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1192     *
1193     * **Complexity**: Linear in the size of *this.
1194     *
1195     * **Exceptions**: Strong exception guarantee.
1196     *
1197     * **Throws**: `length_error` if `new_capacity > max_size()`.
1198     */
1199    inline void reserve_front(size_type new_capacity)
1200    {
1201       if (front_capacity() >= new_capacity) { return; }
1202 
1203       reallocate_at(new_capacity + back_free_capacity(), new_capacity - size());
1204 
1205       BOOST_ASSERT(invariants_ok());
1206    }
1207 
1208    /**
1209     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1210     *
1211     * **Effects**: Ensures that `n` elements can be pushed to the back
1212     * without requiring reallocation, where `n` is `new_capacity - size()`,
1213     * if `n` is positive. Otherwise, there are no effects.
1214     * Invalidates iterators if reallocation is needed.
1215     *
1216     * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1217     *
1218     * **Complexity**: Linear in the size of *this.
1219     *
1220     * **Exceptions**: Strong exception guarantee.
1221     *
1222     * **Throws**: length_error if `new_capacity > max_size()`.
1223     */
1224    inline void reserve_back(size_type new_capacity)
1225    {
1226       if (back_capacity() >= new_capacity) { return; }
1227 
1228       reallocate_at(new_capacity + front_free_capacity(), m_.front_idx);
1229 
1230       BOOST_ASSERT(invariants_ok());
1231    }
1232 
1233 
1234    /**
1235     * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1236     *
1237     * **Effects**: Reduces `capacity()` to `size()`. Invalidates iterators.
1238     *
1239     * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1240     *
1241     * **Exceptions**: Strong exception guarantee.
1242     *
1243     * **Complexity**: Linear in the size of *this.
1244     */
1245    inline void shrink_to_fit()
1246    {
1247       if(this->front_capacity() || this->back_capacity())
1248             this->reallocate_at(size(), 0);
1249    }
1250 
1251    // element access:
1252 
1253    /**
1254     * **Returns**: A reference to the `n`th element in the devector.
1255     *
1256     * **Precondition**: `n < size()`.
1257     *
1258     * **Complexity**: Constant.
1259     */
1260    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1261    reference operator[](size_type n) BOOST_NOEXCEPT
1262    {
1263       BOOST_ASSERT(n < size());
1264       return m_.buffer[m_.front_idx + n];
1265    }
1266 
1267    /**
1268     * **Returns**: A constant reference to the `n`th element in the devector.
1269     *
1270     * **Precondition**: `n < size()`.
1271     *
1272     * **Complexity**: Constant.
1273     */
1274    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1275    const_reference operator[](size_type n) const BOOST_NOEXCEPT
1276    {
1277       BOOST_ASSERT(n < size());
1278       return m_.buffer[m_.front_idx + n];
1279    }
1280 
1281    //! <b>Requires</b>: size() >= n.
1282    //!
1283    //! <b>Effects</b>: Returns an iterator to the nth element
1284    //!   from the beginning of the container. Returns end()
1285    //!   if n == size().
1286    //!
1287    //! <b>Throws</b>: Nothing.
1288    //!
1289    //! <b>Complexity</b>: Constant.
1290    //!
1291    //! <b>Note</b>: Non-standard extension
1292    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1293       iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1294    {
1295       BOOST_ASSERT(n <= size());
1296       return iterator(m_.buffer + (m_.front_idx + n));
1297    }
1298 
1299    //! <b>Requires</b>: size() >= n.
1300    //!
1301    //! <b>Effects</b>: Returns a const_iterator to the nth element
1302    //!   from the beginning of the container. Returns end()
1303    //!   if n == size().
1304    //!
1305    //! <b>Throws</b>: Nothing.
1306    //!
1307    //! <b>Complexity</b>: Constant.
1308    //!
1309    //! <b>Note</b>: Non-standard extension
1310    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1311       const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1312    {
1313       BOOST_ASSERT(n <= size());
1314       return const_iterator(m_.buffer + (m_.front_idx + n));
1315    }
1316 
1317    //! <b>Requires</b>: begin() <= p <= end().
1318    //!
1319    //! <b>Effects</b>: Returns the index of the element pointed by p
1320    //!   and size() if p == end().
1321    //!
1322    //! <b>Throws</b>: Nothing.
1323    //!
1324    //! <b>Complexity</b>: Constant.
1325    //!
1326    //! <b>Note</b>: Non-standard extension
1327    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1328       size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1329    {
1330       BOOST_ASSERT(p >= begin());
1331       BOOST_ASSERT(p <= end());
1332       return static_cast<size_type>(p - this->begin());
1333    }
1334 
1335    //! <b>Requires</b>: begin() <= p <= end().
1336    //!
1337    //! <b>Effects</b>: Returns the index of the element pointed by p
1338    //!   and size() if p == end().
1339    //!
1340    //! <b>Throws</b>: Nothing.
1341    //!
1342    //! <b>Complexity</b>: Constant.
1343    //!
1344    //! <b>Note</b>: Non-standard extension
1345    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1346       size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1347    {
1348       BOOST_ASSERT(p >= cbegin());
1349       BOOST_ASSERT(p <= cend());
1350       return static_cast<size_type>(p - this->cbegin());
1351    }
1352 
1353    /**
1354    * **Returns**: A reference to the `n`th element in the devector.
1355    *
1356    * **Throws**: `out_of_range`, if `n >= size()`.
1357    *
1358    * **Complexity**: Constant.
1359    */
1360    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1361       reference at(size_type n)
1362    {
1363       if (size() <= n)
1364             throw_out_of_range("devector::at out of range");
1365       return (*this)[n];
1366    }
1367 
1368    /**
1369    * **Returns**: A constant reference to the `n`th element in the devector.
1370    *
1371    * **Throws**: `out_of_range`, if `n >= size()`.
1372    *
1373    * **Complexity**: Constant.
1374    */
1375    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1376       const_reference at(size_type n) const
1377    {
1378       if (size() <= n)
1379             throw_out_of_range("devector::at out of range");
1380       return (*this)[n];
1381    }
1382 
1383    /**
1384    * **Returns**: A reference to the first element in the devector.
1385    *
1386    * **Precondition**: `!empty()`.
1387    *
1388    * **Complexity**: Constant.
1389    */
1390    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1391       reference front() BOOST_NOEXCEPT
1392    {
1393       BOOST_ASSERT(!empty());
1394 
1395       return m_.buffer[m_.front_idx];
1396    }
1397 
1398    /**
1399    * **Returns**: A constant reference to the first element in the devector.
1400    *
1401    * **Precondition**: `!empty()`.
1402    *
1403    * **Complexity**: Constant.
1404    */
1405    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1406       const_reference front() const BOOST_NOEXCEPT
1407    {
1408       BOOST_ASSERT(!empty());
1409 
1410       return m_.buffer[m_.front_idx];
1411    }
1412 
1413    /**
1414    * **Returns**: A reference to the last element in the devector.
1415    *
1416    * **Precondition**: `!empty()`.
1417    *
1418    * **Complexity**: Constant.
1419    */
1420    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1421       reference back() BOOST_NOEXCEPT
1422    {
1423       BOOST_ASSERT(!empty());
1424 
1425       return m_.buffer[m_.back_idx - 1u];
1426    }
1427 
1428    /**
1429    * **Returns**: A constant reference to the last element in the devector.
1430    *
1431    * **Precondition**: `!empty()`.
1432    *
1433    * **Complexity**: Constant.
1434    */
1435    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1436       const_reference back() const BOOST_NOEXCEPT
1437    {
1438       BOOST_ASSERT(!empty());
1439 
1440       return m_.buffer[m_.back_idx - 1u];
1441    }
1442 
1443    /**
1444    * **Returns**: A pointer to the underlying array serving as element storage.
1445    * The range `[data(); data() + size())` is always valid. For a non-empty devector,
1446    * `data() == &front()`.
1447    *
1448    * **Complexity**: Constant.
1449    */
1450    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1451       T* data() BOOST_NOEXCEPT
1452    {
1453       return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
1454    }
1455 
1456    /**
1457    * **Returns**: A constant pointer to the underlying array serving as element storage.
1458    * The range `[data(); data() + size())` is always valid. For a non-empty devector,
1459    * `data() == &front()`.
1460    *
1461    * **Complexity**: Constant.
1462    */
1463    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1464       const T* data() const BOOST_NOEXCEPT
1465    {
1466       return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
1467    }
1468 
1469    // modifiers:
1470 
1471    /**
1472    * **Effects**: Pushes a new element to the front of the devector.
1473    * The element is constructed in-place, using the perfect forwarded `args`
1474    * as constructor arguments. Invalidates iterators if reallocation is needed.
1475    * (`front_free_capacity() == 0`)
1476    *
1477    * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`.
1478    *
1479    * **Exceptions**: Strong exception guarantee.
1480    *
1481    * **Complexity**: Amortized constant in the size of `*this`.
1482    * (Constant, if `front_free_capacity() > 0`)
1483    *
1484    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1485    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1486    */
1487    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1488    template <class... Args>
1489    reference emplace_front(Args&&... args)
1490    {
1491       if (BOOST_LIKELY(front_free_capacity() != 0)) // fast path
1492       {
1493          pointer const p = m_.buffer + (m_.front_idx - 1u);
1494          this->alloc_construct(p, boost::forward<Args>(args)...);
1495          --m_.front_idx;
1496          BOOST_ASSERT(invariants_ok());
1497          return *p;
1498       }
1499       else
1500       {
1501          typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1502          return *this->insert_range_slow_path(this->begin(), 1, proxy_t(::boost::forward<Args>(args)...));
1503       }
1504    }
1505 
1506    #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1507 
1508    #define BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT(N) \
1509    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1510    inline reference emplace_front(BOOST_MOVE_UREF##N)\
1511    {\
1512       if (front_free_capacity())\
1513       {\
1514          pointer const p = m_.buffer + (m_.front_idx - 1u);\
1515          this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1516          --m_.front_idx;\
1517          return *p;\
1518       }\
1519       else\
1520       {\
1521          typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1522          return *this->insert_range_slow_path(this->begin(), 1, proxy_t(BOOST_MOVE_FWD##N));\
1523       }\
1524    }\
1525    //
1526    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT)
1527    #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT
1528 
1529    #endif
1530 
1531    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1532    /**
1533    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1534    *
1535    * **Effects**: Pushes the copy of `x` to the front of the devector.
1536    * Invalidates iterators if reallocation is needed.
1537    * (`front_free_capacity() == 0`)
1538    *
1539    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1540    *
1541    * **Exceptions**: Strong exception guarantee.
1542    *
1543    * **Complexity**: Amortized constant in the size of `*this`.
1544    * (Constant, if `front_free_capacity() > 0`)
1545    */
1546    void push_front(const T& x);
1547 
1548    /**
1549    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1550    *
1551    * **Effects**: Move constructs a new element at the front of the devector using `x`.
1552    * Invalidates iterators if reallocation is needed.
1553    * (`front_free_capacity() == 0`)
1554    *
1555    * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1556    *
1557    * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
1558    *
1559    * **Complexity**: Amortized constant in the size of `*this`.
1560    * (Constant, if `front_free_capacity() > 0`)
1561    */
1562    void push_front(T&& x);
1563 
1564    #else
1565    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
1566    #endif
1567 
1568    /**
1569    * **Effects**: Removes the first element of `*this`.
1570    *
1571    * **Precondition**: `!empty()`.
1572    *
1573    * **Postcondition**: `front_free_capacity()` is incremented by 1.
1574    *
1575    * **Complexity**: Constant.
1576    */
1577    void pop_front() BOOST_NOEXCEPT
1578    {
1579       BOOST_ASSERT(!empty());
1580       allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(m_.buffer + m_.front_idx));
1581       ++m_.front_idx;
1582       BOOST_ASSERT(invariants_ok());
1583    }
1584 
1585    /**
1586    * **Effects**: Pushes a new element to the back of the devector.
1587    * The element is constructed in-place, using the perfect forwarded `args`
1588    * as constructor arguments. Invalidates iterators if reallocation is needed.
1589    * (`back_free_capacity() == 0`)
1590    *
1591    * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`,
1592    * and [MoveAssignable].
1593    *
1594    * **Exceptions**: Strong exception guarantee.
1595    *
1596    * **Complexity**: Amortized constant in the size of `*this`.
1597    * (Constant, if `back_free_capacity() > 0`)
1598    *
1599    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1600    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1601    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1602    */
1603    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1604    template <class... Args>
1605    inline reference emplace_back(Args&&... args)
1606    {
1607       if (BOOST_LIKELY(this->back_free_capacity() != 0)){
1608          pointer const p = m_.buffer + m_.back_idx;
1609          this->alloc_construct(p, boost::forward<Args>(args)...);
1610          ++m_.back_idx;
1611          BOOST_ASSERT(invariants_ok());
1612          return *p;
1613       }
1614       else {
1615          typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1616          return *this->insert_range_slow_path(this->end(), 1, proxy_t(::boost::forward<Args>(args)...));
1617       }
1618    }
1619 
1620    #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1621 
1622    #define BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK(N) \
1623    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1624    inline reference emplace_back(BOOST_MOVE_UREF##N)\
1625    {\
1626       if (this->back_free_capacity()){\
1627          pointer const p = m_.buffer + m_.back_idx;\
1628          this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1629          ++m_.back_idx;\
1630          return *p;\
1631       }\
1632       else {\
1633          typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1634          return *this->insert_range_slow_path(this->end(), 1, proxy_t(BOOST_MOVE_FWD##N));\
1635       }\
1636    }\
1637    //
1638    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK)
1639    #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK
1640 
1641    #endif    //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1642 
1643 
1644    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1645    /**
1646    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1647    *
1648    * **Effects**: Pushes the copy of `x` to the back of the devector.
1649    * Invalidates iterators if reallocation is needed.
1650    * (`back_free_capacity() == 0`)
1651    *
1652    * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1653    *
1654    * **Exceptions**: Strong exception guarantee.
1655    *
1656    * **Complexity**: Amortized constant in the size of `*this`.
1657    * (Constant, if `back_free_capacity() > 0`)
1658    */
1659    void push_back(const T& x);
1660 
1661    /**
1662    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1663    *
1664    * **Effects**: Move constructs a new element at the back of the devector using `x`.
1665    * Invalidates iterators if reallocation is needed.
1666    * (`back_free_capacity() == 0`)
1667    *
1668    * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1669    *
1670    * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
1671    *
1672    * **Complexity**: Amortized constant in the size of `*this`.
1673    * (Constant, if `back_free_capacity() > 0`)
1674    */
1675    void push_back(T&& x);
1676 
1677    #else
1678    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1679    #endif
1680 
1681    /**
1682    * **Effects**: Removes the last element of `*this`.
1683    *
1684    * **Precondition**: `!empty()`.
1685    *
1686    * **Postcondition**: `back_free_capacity()` is incremented by 1.
1687    *
1688    * **Complexity**: Constant.
1689    */
1690    void pop_back() BOOST_NOEXCEPT
1691    {
1692       BOOST_ASSERT(! empty());
1693       --m_.back_idx;
1694       allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(m_.buffer + m_.back_idx));
1695       BOOST_ASSERT(invariants_ok());
1696    }
1697 
1698    /**
1699    * **Effects**: Constructs a new element before the element pointed by `position`.
1700    * The element is constructed in-place, using the perfect forwarded `args`
1701    * as constructor arguments. Invalidates iterators if reallocation is needed.
1702    *
1703    * **Requires**: `T` shall be [EmplaceConstructible], and [MoveInsertable] into `*this`,
1704    * and [MoveAssignable].
1705    *
1706    * **Returns**: Iterator pointing to the newly constructed element.
1707    *
1708    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1709    * and `NothrowAssignable`, Basic exception guarantee otherwise.
1710    *
1711    * **Complexity**: Linear in the size of `*this`.
1712    *
1713    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1714    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1715    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1716    */
1717    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1718    template <class... Args>
1719    iterator emplace(const_iterator position, Args&&... args)
1720    {
1721       BOOST_ASSERT(position >= begin());
1722       BOOST_ASSERT(position <= end());
1723       typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1724       bool prefer_move_back;
1725       if (position == end()){
1726          if(back_free_capacity()) // fast path
1727          {
1728             pointer const p = m_.buffer + m_.back_idx;
1729             this->alloc_construct(p, boost::forward<Args>(args)...);
1730             ++m_.back_idx;
1731             return iterator(p);
1732          }
1733          prefer_move_back = true;
1734       }
1735       else if (position == begin()){
1736          if(front_free_capacity()) // secondary fast path
1737          {
1738             pointer const p = m_.buffer + (m_.front_idx - 1);
1739             this->alloc_construct(p, boost::forward<Args>(args)...);
1740             --m_.front_idx;
1741             return iterator(p);
1742          }
1743          prefer_move_back = false;
1744       }
1745       else{
1746          iterator nonconst_pos = unconst_iterator(position);
1747          prefer_move_back = should_move_back(position);
1748 
1749          if(prefer_move_back){
1750             if(back_free_capacity()){
1751                boost::container::expand_forward_and_insert_nonempty_middle_alloc
1752                   ( get_allocator_ref()
1753                   , boost::movelib::to_raw_pointer(nonconst_pos)
1754                   , this->priv_raw_end()
1755                   , 1, proxy_t(::boost::forward<Args>(args)...));
1756                ++m_.back_idx;
1757                return nonconst_pos;
1758             }
1759          }
1760          else{
1761             if (front_free_capacity()){
1762                boost::container::expand_backward_and_insert_nonempty_middle_alloc
1763                (get_allocator_ref()
1764                   , this->priv_raw_begin()
1765                   , boost::movelib::to_raw_pointer(nonconst_pos)
1766                   , 1, proxy_t(::boost::forward<Args>(args)...));
1767                --m_.front_idx;
1768                return --nonconst_pos;
1769             }
1770          }
1771       }
1772       return this->insert_range_slow_path(position, 1, proxy_t(::boost::forward<Args>(args)...));
1773    }
1774 
1775    #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1776 
1777    #define BOOST_CONTAINER_DEVECTOR_EMPLACE(N) \
1778    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1779    iterator emplace(const_iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1780    {\
1781       BOOST_ASSERT(position >= begin());\
1782       BOOST_ASSERT(position <= end());\
1783       typedef dtl::insert_emplace_proxy_arg##N<allocator_type  BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1784       bool prefer_move_back;\
1785       if (position == end()){\
1786          if(back_free_capacity())\
1787          {\
1788             pointer const p = m_.buffer + m_.back_idx;\
1789             this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1790             ++m_.back_idx;\
1791             return iterator(p);\
1792          }\
1793          prefer_move_back = true;\
1794       }\
1795       else if (position == begin()){\
1796          if(front_free_capacity())\
1797          {\
1798             pointer const p = m_.buffer + (m_.front_idx - 1);\
1799             this->alloc_construct(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1800             --m_.front_idx;\
1801             return iterator(p);\
1802          }\
1803          prefer_move_back = false;\
1804       }\
1805       else{\
1806          iterator nonconst_pos = unconst_iterator(position);\
1807          prefer_move_back = should_move_back(position);\
1808          \
1809          if(prefer_move_back){\
1810             if(back_free_capacity()){\
1811                boost::container::expand_forward_and_insert_nonempty_middle_alloc\
1812                   ( get_allocator_ref()\
1813                   , boost::movelib::to_raw_pointer(nonconst_pos)\
1814                   , this->priv_raw_end()\
1815                   , 1, proxy_t(BOOST_MOVE_FWD##N));\
1816                ++m_.back_idx;\
1817                return nonconst_pos;\
1818             }\
1819          }\
1820          else{\
1821             if (front_free_capacity()){\
1822                boost::container::expand_backward_and_insert_nonempty_middle_alloc\
1823                (get_allocator_ref()\
1824                   , this->priv_raw_begin()\
1825                   , boost::movelib::to_raw_pointer(nonconst_pos)\
1826                   , 1, proxy_t(BOOST_MOVE_FWD##N));\
1827                --m_.front_idx;\
1828                return --nonconst_pos;\
1829             }\
1830          }\
1831       }\
1832       return this->insert_range_slow_path(position, 1, proxy_t(BOOST_MOVE_FWD##N));\
1833    }\
1834    //
1835    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE)
1836    #undef BOOST_CONTAINER_DEVECTOR_EMPLACE
1837 
1838    #endif    //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1839 
1840 
1841    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1842    /**
1843    * **Effects**: Copy constructs a new element before the element pointed by `position`,
1844    * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1845    *
1846    * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
1847    *
1848    * **Returns**: Iterator pointing to the newly constructed element.
1849    *
1850    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1851    * and `NothrowAssignable`, Basic exception guarantee otherwise.
1852    *
1853    * **Complexity**: Linear in the size of `*this`.
1854    *
1855    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1856    * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1857    */
1858    iterator insert(const_iterator position, const T &x);
1859 
1860    /**
1861    * **Effects**: Move constructs a new element before the element pointed by `position`,
1862    * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1863    *
1864    * **Requires**: `T` shall be [MoveInsertable] into `*this` and and [CopyAssignable].
1865    *
1866    * **Returns**: Iterator pointing to the newly constructed element.
1867    *
1868    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1869    * and `NothrowAssignable` (not regarding the state of `x`),
1870    * Basic exception guarantee otherwise.
1871    *
1872    * **Complexity**: Linear in the size of `*this`.
1873    *
1874    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1875    * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1876    */
1877    iterator insert(const_iterator position, T &&x);
1878    #else
1879    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1880    #endif
1881 
1882    /**
1883    * **Effects**: Copy constructs `n` elements before the element pointed by `position`,
1884    * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1885    *
1886    * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
1887    *
1888    * **Returns**: Iterator pointing to the first inserted element, or `position`, if `n` is zero.
1889    *
1890    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1891    * and `NothrowAssignable`, Basic exception guarantee otherwise.
1892    *
1893    * **Complexity**: Linear in the size of `*this` and `n`.
1894    *
1895    * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1896    * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1897    */
1898    inline iterator insert(const_iterator position, size_type n, const T& x)
1899    {
1900       cvalue_iterator first(x, n);
1901       cvalue_iterator last = first + n;
1902       return this->insert_range(position, first, last);
1903    }
1904 
1905    /**
1906    * **Effects**: Copy constructs elements before the element pointed by position
1907    * using each element in the range pointed by `first` and `last` as constructor arguments.
1908    * Invalidates iterators if reallocation is needed.
1909    *
1910    * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified iterator
1911    * does not meet the forward iterator requirements, `T` shall also be [MoveInsertable] into `*this`
1912    * and [MoveAssignable].
1913    *
1914    * **Precondition**: `first` and `last` are not iterators into `*this`.
1915    *
1916    * **Returns**: Iterator pointing to the first inserted element, or `position`, if `first == last`.
1917    *
1918    * **Complexity**: Linear in the size of `*this` and `N` (where `N` is the distance between `first` and `last`).
1919    * Makes only `N` calls to the constructor of `T` and no reallocations if iterators `first` and `last`
1920    * are of forward, bidirectional, or random access categories. It makes 2N calls to the copy constructor of `T`
1921    * and `O(log(N)) reallocations if they are just input iterators.
1922    *
1923    * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1924    * and `NothrowAssignable`, Basic exception guarantee otherwise.
1925    *
1926    * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
1927    * unless an exception is thrown.
1928    *
1929    * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1930    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1931    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1932    */
1933    template <class InputIterator>
1934    iterator insert(const_iterator position, InputIterator first, InputIterator last
1935       //Input iterators
1936       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1937             < void
1938             BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
1939             BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
1940             >::type * = 0)
1941       )
1942    {
1943       if (position == end())
1944       {
1945          size_type insert_index = size();
1946 
1947          for (; first != last; ++first)
1948          {
1949             this->emplace_back(*first);
1950          }
1951 
1952          return begin() + insert_index;
1953       }
1954       else
1955       {
1956          const size_type insert_index = static_cast<size_type>(position - this->cbegin());
1957          const size_type old_size = static_cast<size_type>(this->size());
1958 
1959          for (; first != last; ++first) {
1960             this->emplace_back(*first);
1961          }
1962          iterator rit (this->begin() + insert_index);
1963          boost::movelib::rotate_gcd(rit, this->begin() + old_size, this->begin() + this->size());
1964          return rit;
1965       }
1966    }
1967 
1968    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1969 
1970    template <class ForwardIterator>
1971    inline iterator insert(const_iterator position, ForwardIterator first, ForwardIterator last
1972       //Other iterators
1973       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1974             < void
1975             BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
1976             BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
1977             >::type * = 0)
1978       )
1979    {
1980       return insert_range(position, first, last);
1981    }
1982 
1983    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1984 
1985    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1986    /** **Equivalent to**: `insert(position, il.begin(), il.end())` */
1987    inline iterator insert(const_iterator position, std::initializer_list<T> il)
1988    {
1989       return this->insert(position, il.begin(), il.end());
1990    }
1991    #endif
1992 
1993    /**
1994    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1995    *
1996    * **Effects**: Destroys the element pointed by `position` and removes it from the devector.
1997    * Invalidates iterators.
1998    *
1999    * **Requires**: `T` shall be [MoveAssignable].
2000    *
2001    * **Precondition**: `position` must be in the range of `[begin(), end())`.
2002    *
2003    * **Returns**: Iterator pointing to the element immediately following the erased element
2004    * prior to its erasure. If no such element exists, `end()` is returned.
2005    *
2006    * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
2007    * Basic exception guarantee otherwise.
2008    *
2009    * **Complexity**: Linear in half the size of `*this`.
2010    */
2011    iterator erase(const_iterator position)
2012    {
2013       return erase(position, position + 1);
2014    }
2015 
2016    /**
2017    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
2018    *
2019    * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
2020    * Invalidates iterators.
2021    *
2022    * **Requires**: `T` shall be [MoveAssignable].
2023    *
2024    * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
2025    *
2026    * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
2027    * being erased. If no such element exists, `end()` is returned.
2028    *
2029    * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
2030    * Basic exception guarantee otherwise.
2031    *
2032    * **Complexity**: Linear in half the size of `*this`
2033    * plus the distance between `first` and `last`.
2034    */
2035    iterator erase(const_iterator first, const_iterator last)
2036    {
2037       iterator nc_first = unconst_iterator(first);
2038       iterator nc_last  = unconst_iterator(last);
2039       return erase(nc_first, nc_last);
2040    }
2041 
2042    /**
2043    * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
2044    *
2045    * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
2046    * Invalidates iterators.
2047    *
2048    * **Requires**: `T` shall be [MoveAssignable].
2049    *
2050    * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
2051    *
2052    * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
2053    * being erased. If no such element exists, `end()` is returned.
2054    *
2055    * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
2056    * Basic exception guarantee otherwise.
2057    *
2058    * **Complexity**: Linear in half the size of `*this`.
2059    */
2060    iterator erase(iterator first, iterator last)
2061    {
2062       size_type front_distance = pos_to_index(last);
2063       size_type back_distance  = size_type(end() - first);
2064       size_type n = boost::container::iterator_udistance(first, last);
2065 
2066       if (front_distance < back_distance)
2067       {
2068             // move n to the right
2069             boost::container::move_backward(begin(), first, last);
2070 
2071             for (iterator i = begin(); i != begin() + n; ++i)
2072             {
2073                allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i));
2074             }
2075             //n is always less than max stored_size_type
2076             m_.set_front_idx(m_.front_idx + n);
2077 
2078             BOOST_ASSERT(invariants_ok());
2079             return last;
2080       }
2081       else {
2082             // move n to the left
2083             boost::container::move(last, end(), first);
2084 
2085             for (iterator i = end() - n; i != end(); ++i)
2086             {
2087                allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(i));
2088             }
2089             //n is always less than max stored_size_type
2090             m_.set_back_idx(m_.back_idx - n);
2091 
2092             BOOST_ASSERT(invariants_ok());
2093             return first;
2094       }
2095    }
2096 
2097    /**
2098    * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
2099    *
2100    * **Effects**: exchanges the contents of `*this` and `b`.
2101    *
2102    * **Requires**: instances of `T` must be swappable by unqualified call of `swap`
2103    * and `T` must be [MoveInsertable] into `*this`.
2104    *
2105    * **Precondition**: The allocators should allow propagation or should compare equal.
2106    *
2107    * **Exceptions**: Basic exceptions guarantee if not `noexcept`.
2108    *
2109    * **Complexity**: Constant.
2110    */
2111    void swap(devector& b)
2112       BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
2113                                  || allocator_traits_type::is_always_equal::value)
2114    {
2115       BOOST_CONSTEXPR_OR_CONST bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
2116       BOOST_ASSERT(propagate_alloc || get_allocator_ref() == b.get_allocator_ref()); // else it's undefined behavior
2117 
2118       swap_big_big(*this, b);
2119 
2120       // swap indices
2121       boost::adl_move_swap(m_.front_idx, b.m_.front_idx);
2122       boost::adl_move_swap(m_.back_idx, b.m_.back_idx);
2123 
2124       //And now swap the allocator
2125       dtl::swap_alloc(this->get_allocator_ref(), b.get_allocator_ref(), dtl::bool_<propagate_alloc>());
2126 
2127       BOOST_ASSERT(   invariants_ok());
2128       BOOST_ASSERT(b.invariants_ok());
2129    }
2130 
2131    /**
2132    * **Effects**: Destroys all elements in the devector.
2133    * Invalidates all references, pointers and iterators to the
2134    * elements of the devector.
2135    *
2136    * **Postcondition**: `empty() && front_free_capacity() == 0
2137    * && back_free_capacity() == old capacity`.
2138    *
2139    * **Complexity**: Linear in the size of `*this`.
2140    *
2141    * **Remarks**: Does not free memory.
2142    */
2143    void clear() BOOST_NOEXCEPT
2144    {
2145       destroy_elements(begin(), end());
2146       m_.front_idx = m_.back_idx = 0;
2147    }
2148 
2149    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2150       friend bool operator==(const devector& x, const devector& y)
2151    {   return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());   }
2152 
2153    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2154       friend bool operator!=(const devector& x, const devector& y)
2155    {   return !(x == y); }
2156 
2157    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2158       friend bool operator< (const devector& x, const devector& y)
2159    {   return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());   }
2160 
2161    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2162       friend bool operator>(const devector& x, const devector& y)
2163    {   return y < x;   }
2164 
2165    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2166       friend bool operator<=(const devector& x, const devector& y)
2167    {   return !(y < x);   }
2168 
2169    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2170       friend bool operator>=(const devector& x, const devector& y)
2171    {   return !(x < y);   }
2172 
2173    inline friend void swap(devector& x, devector& y)
2174       BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
2175                                  || allocator_traits_type::is_always_equal::value)
2176    {   x.swap(y);   }
2177 
2178    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2179 
2180    //Functions for optimizations, not for users
2181    T *unused_storage(size_type &sz)
2182    {
2183       T *const storage_addr = boost::movelib::to_raw_pointer(m_.buffer);
2184       if(this->empty()){
2185          sz = m_.capacity;
2186          return storage_addr;
2187       }
2188       else if(this->back_free_capacity() > this->front_free_capacity()){
2189          sz = this->back_free_capacity();
2190          return storage_addr + m_.back_idx;
2191       }
2192       else{
2193          sz = this->front_free_capacity();
2194          return storage_addr;
2195       }
2196    }
2197 
2198    #endif
2199 
2200    private:
2201 
2202    void priv_move_assign(BOOST_RV_REF(devector) x, dtl::bool_<true> /*steal_resources*/)
2203    {
2204       this->clear();
2205       this->deallocate_buffer();
2206 
2207       //Move allocator if needed
2208       dtl::bool_<allocator_traits_type::
2209          propagate_on_container_move_assignment::value> flag;
2210       dtl::move_alloc(this->get_allocator_ref(), x.get_allocator_ref(), flag);
2211 
2212       m_.capacity = x.m_.capacity;
2213       m_.buffer = x.m_.buffer;
2214       m_.front_idx = x.m_.front_idx;
2215       m_.back_idx = x.m_.back_idx;
2216 
2217       // leave x in valid state
2218       x.m_.capacity = 0u;
2219       x.m_.buffer = pointer();
2220       x.m_.back_idx = x.m_.front_idx = 0;
2221    }
2222 
2223    void priv_move_assign(BOOST_RV_REF(devector) x, dtl::bool_<false> /*steal_resources*/)
2224    {
2225       //We can't guarantee a compile-time equal allocator or propagation so fallback to runtime
2226       //Resources can be transferred if both allocators are equal
2227       if (get_allocator_ref() == x.get_allocator_ref()) {
2228          this->priv_move_assign(boost::move(x), dtl::true_());
2229       }
2230       else {
2231          // We can't steal memory.
2232          move_iterator<iterator> xbegin = boost::make_move_iterator(x.begin());
2233          move_iterator<iterator> xend = boost::make_move_iterator(x.end());
2234 
2235          //Move allocator if needed
2236          dtl::bool_<allocator_traits_type::
2237             propagate_on_container_move_assignment::value> flag;
2238          dtl::move_alloc(this->get_allocator_ref(), x.get_allocator_ref(), flag);
2239 
2240          if (m_.capacity >= x.size()) {
2241             overwrite_buffer(xbegin, xend);
2242          }
2243          else {
2244             allocate_and_copy_range(xbegin, xend);
2245          }
2246       }
2247    }
2248 
2249    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2250    size_type pos_to_index(const_iterator i) const 
2251    {
2252       return static_cast<size_type>(i - cbegin());
2253    }
2254 
2255    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
2256    bool should_move_back(const_iterator i) const 
2257    {
2258       return static_cast<size_type>(this->pos_to_index(i)) >= this->size()/2u;
2259    }
2260 
2261    inline static iterator unconst_iterator(const_iterator i)
2262    {
2263       return boost::intrusive::pointer_traits<pointer>::const_cast_from(i);
2264    }
2265 
2266    inline size_type front_capacity() const
2267    {
2268       return m_.back_idx;
2269    }
2270 
2271    inline size_type back_capacity() const
2272    {
2273       return size_type(m_.capacity - m_.front_idx);
2274    }
2275 
2276    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2277 
2278    inline T* priv_raw_begin() BOOST_NOEXCEPT
2279    {   return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;   }
2280 
2281    inline T* priv_raw_end() BOOST_NOEXCEPT
2282    {   return boost::movelib::to_raw_pointer(m_.buffer) + m_.back_idx;    }
2283 
2284 
2285    template <class U>
2286    inline void priv_push_front(BOOST_FWD_REF(U) u)
2287    {
2288       this->emplace_front(boost::forward<U>(u));
2289    }
2290 
2291    template <class U>
2292    inline void priv_push_back(BOOST_FWD_REF(U) u)
2293    {
2294       this->emplace_back(boost::forward<U>(u));
2295    }
2296 
2297    template <class U>
2298    inline iterator priv_insert(const_iterator pos, BOOST_FWD_REF(U) u)
2299    {
2300       return this->emplace(pos, boost::forward<U>(u));
2301    }
2302 
2303    // allocator_type wrappers
2304 
2305    inline allocator_type& get_allocator_ref() BOOST_NOEXCEPT
2306    {
2307       return static_cast<allocator_type&>(m_);
2308    }
2309 
2310    inline const allocator_type& get_allocator_ref() const BOOST_NOEXCEPT
2311    {
2312       return static_cast<const allocator_type&>(m_);
2313    }
2314 
2315    pointer allocate(size_type cap)
2316    {
2317       pointer const p = impl::do_allocate(get_allocator_ref(), cap);
2318       #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2319       ++m_.capacity_alloc_count;
2320       #endif // BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2321       return p;
2322    }
2323 
2324    void destroy_elements(pointer b, pointer e)
2325    {
2326       for (; b != e; ++b)
2327       {
2328          allocator_traits_type::destroy(get_allocator_ref(), boost::movelib::to_raw_pointer(b));
2329       }
2330    }
2331 
2332    void deallocate_buffer()
2333    {
2334       if (m_.buffer)
2335       {
2336          allocator_traits_type::deallocate(get_allocator_ref(), m_.buffer, m_.capacity);
2337       }
2338    }
2339 
2340    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2341    template <typename... Args>
2342    inline void alloc_construct(pointer dst, Args&&... args)
2343    {
2344       allocator_traits_type::construct(
2345             get_allocator_ref(),
2346             boost::movelib::to_raw_pointer(dst),
2347             boost::forward<Args>(args)...
2348       );
2349    }
2350 
2351    template <typename... Args>
2352    void construct_n(pointer buffer, size_type n, Args&&... args)
2353    {
2354       detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());
2355       guarded_construct_n(buffer, n, ctr_guard, boost::forward<Args>(args)...);
2356       ctr_guard.release();
2357    }
2358 
2359    template <typename... Args>
2360    void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard, Args&&... args)
2361    {
2362       for (size_type i = 0; i < n; ++i) {
2363          this->alloc_construct(buffer + i, boost::forward<Args>(args)...);
2364          ctr_guard.extend();
2365       }
2366    }
2367 
2368    #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2369 
2370    #define BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT(N) \
2371    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2372    inline void alloc_construct(pointer dst BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2373    {\
2374       allocator_traits_type::construct(\
2375             get_allocator_ref(), boost::movelib::to_raw_pointer(dst) BOOST_MOVE_I##N BOOST_MOVE_FWD##N );\
2376    }\
2377    \
2378    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2379    void construct_n(pointer buffer, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2380    {\
2381       detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());\
2382       guarded_construct_n(buffer, n, ctr_guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2383       ctr_guard.release();\
2384    }\
2385    \
2386    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2387    void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2388    {\
2389       for (size_type i = 0; i < n; ++i) {\
2390             this->alloc_construct(buffer + i BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2391             ctr_guard.extend();\
2392       }\
2393    }
2394    //
2395    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT)
2396    #undef BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT
2397 
2398    #endif    //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2399 
2400    size_type calculate_new_capacity(size_type requested_capacity)
2401    {
2402       size_type max = allocator_traits_type::max_size(this->get_allocator_ref());
2403       (clamp_by_stored_size_type)(max, stored_size_type());
2404       const size_type remaining_additional_cap = max - size_type(m_.capacity);
2405       const size_type min_additional_cap = requested_capacity - size_type(m_.capacity);
2406       if ( remaining_additional_cap < min_additional_cap )
2407             boost::container::throw_length_error("devector: get_next_capacity, max size exceeded");
2408 
2409       return growth_factor_type()( size_type(m_.capacity), min_additional_cap, max);
2410    }
2411 
2412    void buffer_move_or_copy(pointer dst)
2413    {
2414       detail::construction_guard<allocator_type> guard(dst, get_allocator_ref());
2415 
2416       buffer_move_or_copy(dst, guard);
2417 
2418       guard.release();
2419    }
2420 
2421    void buffer_move_or_copy(pointer dst, detail::construction_guard<allocator_type>& guard)
2422    {
2423       opt_move_or_copy(begin(), end(), dst, guard);
2424 
2425       destroy_elements(data(), data() + size());
2426       deallocate_buffer();
2427    }
2428 
2429    template <typename Guard>
2430    void opt_move_or_copy(pointer b, pointer e, pointer dst, Guard& guard)
2431    {
2432       // if trivial copy and default allocator, memcpy
2433       boost::container::uninitialized_move_alloc(get_allocator_ref(), b, e, dst);
2434       guard.extend();
2435    }
2436 
2437    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2438 
2439    template <typename... Args>
2440    void resize_impl(size_type sz, Args&&... args)
2441    {
2442       const size_type old_sz = this->size();
2443       if (sz > old_sz)
2444       {
2445          const size_type n = sz - old_sz;
2446 
2447          if (sz <= m_.capacity)
2448          {
2449             //Construct at back
2450             const size_type bfc = this->back_free_capacity();
2451             const size_type b = n < bfc ? n : bfc;
2452             construct_n(m_.buffer + m_.back_idx, b, boost::forward<Args>(args)...);
2453             m_.set_back_idx(m_.back_idx + b);
2454 
2455             //Construct remaining at front
2456             const size_type f = n - b;
2457             construct_n(m_.buffer + m_.front_idx - f, f, boost::forward<Args>(args)...);
2458             m_.set_front_idx(m_.front_idx - f);
2459          }
2460          else
2461          {
2462             resize_back_slow_path(sz, n, boost::forward<Args>(args)...);
2463          }
2464       }
2465       else
2466       {
2467          const size_type n = old_sz - sz;
2468          const size_type new_bidx = m_.back_idx - n;
2469          destroy_elements(m_.buffer + new_bidx, m_.buffer + m_.back_idx);
2470          m_.set_back_idx(new_bidx);
2471       }
2472    }
2473 
2474    template <typename... Args>
2475    void resize_front_impl(size_type sz , Args&&... args)
2476    {
2477       const size_type old_sz = this->size();
2478       if (sz > old_sz)
2479       {
2480          const size_type n = sz - old_sz;
2481 
2482          if (sz <= this->front_capacity())
2483          {
2484             construct_n(m_.buffer + m_.front_idx - n, n, boost::forward<Args>(args)...);
2485             m_.set_front_idx(m_.front_idx - n);
2486          }
2487          else
2488          {
2489             resize_front_slow_path(sz, n, boost::forward<Args>(args)...);
2490          }
2491       }
2492       else {
2493          const size_type n = old_sz - sz;
2494          const size_type new_fidx = m_.front_idx + n;
2495          destroy_elements(m_.buffer + m_.front_idx, m_.buffer + new_fidx);
2496          m_.set_front_idx(new_fidx);
2497       }
2498    }
2499 
2500    template <typename... Args>
2501    void resize_front_slow_path(size_type sz, size_type n, Args&&... args)
2502    {
2503       const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());
2504       pointer new_buffer = allocate(new_capacity);
2505       allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2506 
2507       const size_type old_sz = this->size();
2508       const size_type new_old_elem_index = new_capacity - old_sz;
2509       const size_type new_elem_index = new_old_elem_index - n;
2510 
2511       detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());
2512       guarded_construct_n(new_buffer + new_elem_index, n, guard, boost::forward<Args>(args)...);
2513 
2514       buffer_move_or_copy(new_buffer + new_old_elem_index, guard);
2515 
2516       guard.release();
2517       new_buffer_guard.release();
2518 
2519       m_.buffer = new_buffer;
2520       m_.set_capacity(new_capacity);
2521       m_.set_front_idx(new_elem_index);
2522       m_.set_back_idx(new_elem_index + old_sz + n);
2523    }
2524 
2525    template <typename... Args>
2526    void resize_back_impl(size_type sz, Args&&... args)
2527    {
2528       const size_type old_sz = this->size();
2529       if (sz > old_sz)
2530       {
2531          const size_type n = sz - old_sz;
2532 
2533          if (sz <= this->back_capacity())
2534          {
2535             construct_n(m_.buffer + m_.back_idx, n, boost::forward<Args>(args)...);
2536             m_.set_back_idx(m_.back_idx + n);
2537          }
2538          else
2539          {
2540             resize_back_slow_path(sz, n, boost::forward<Args>(args)...);
2541          }
2542       }
2543       else
2544       {
2545          const size_type n = old_sz - sz;
2546          const size_type new_bidx = m_.back_idx - n;
2547          destroy_elements(m_.buffer + new_bidx, m_.buffer + m_.back_idx);
2548          m_.set_back_idx(new_bidx);
2549       }
2550    }
2551 
2552    template <typename... Args>
2553    void resize_back_slow_path(size_type sz, size_type n, Args&&... args)
2554    {
2555       const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());
2556       pointer new_buffer = allocate(new_capacity);
2557       allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2558 
2559       detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());
2560       guarded_construct_n(new_buffer + m_.back_idx, n, guard, boost::forward<Args>(args)...);
2561 
2562       buffer_move_or_copy(new_buffer + m_.front_idx);
2563 
2564       guard.release();
2565       new_buffer_guard.release();
2566 
2567       m_.buffer = new_buffer;
2568       m_.set_capacity(new_capacity);
2569       m_.set_back_idx(m_.back_idx + n);
2570    }
2571 
2572    #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2573 
2574    #define BOOST_CONTAINER_DEVECTOR_SLOW_PATH(N) \
2575    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2576    void resize_front_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2577    {\
2578       if (sz > size())\
2579       {\
2580          const size_type n = sz - size();\
2581          if (sz <= front_capacity()){\
2582             construct_n(m_.buffer + m_.front_idx - n, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2583             m_.set_front_idx(m_.front_idx - n);\
2584          }\
2585          else\
2586          {\
2587             resize_front_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2588          }\
2589       }\
2590       else {\
2591          while (this->size() > sz)\
2592          {\
2593             this->pop_front();\
2594          }\
2595       }\
2596    }\
2597    \
2598    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2599    void resize_front_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2600    {\
2601       const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());\
2602       pointer new_buffer = allocate(new_capacity);\
2603       allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
2604    \
2605       const size_type new_old_elem_index = new_capacity - size();\
2606       const size_type new_elem_index = new_old_elem_index - n;\
2607    \
2608       detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());\
2609       guarded_construct_n(new_buffer + new_elem_index, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2610    \
2611       buffer_move_or_copy(new_buffer + new_old_elem_index, guard);\
2612    \
2613       guard.release();\
2614       new_buffer_guard.release();\
2615       m_.buffer = new_buffer;\
2616       m_.set_capacity(new_capacity);\
2617       m_.set_back_idx(new_old_elem_index + m_.back_idx - m_.front_idx);\
2618       m_.set_front_idx(new_elem_index);\
2619    }\
2620    \
2621    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2622    void resize_back_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2623    {\
2624       if (sz > size())\
2625       {\
2626          const size_type n = sz - size();\
2627       \
2628          if (sz <= back_capacity())\
2629          {\
2630             construct_n(m_.buffer + m_.back_idx, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2631             m_.set_back_idx(m_.back_idx + n);\
2632          }\
2633          else\
2634          {\
2635             resize_back_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2636          }\
2637       }\
2638       else\
2639       {\
2640          while (size() > sz)\
2641          {\
2642             pop_back();\
2643          }\
2644       }\
2645    }\
2646    \
2647    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2648    void resize_back_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2649    {\
2650       const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());\
2651       pointer new_buffer = allocate(new_capacity);\
2652       allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
2653    \
2654       detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());\
2655       guarded_construct_n(new_buffer + m_.back_idx, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2656    \
2657       buffer_move_or_copy(new_buffer + m_.front_idx);\
2658    \
2659       guard.release();\
2660       new_buffer_guard.release();\
2661    \
2662       m_.buffer = new_buffer;\
2663       m_.set_capacity(new_capacity);\
2664       m_.set_back_idx(m_.back_idx + n);\
2665    }\
2666    \
2667    //
2668    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_SLOW_PATH)
2669    #undef BOOST_CONTAINER_DEVECTOR_SLOW_PATH
2670 
2671    #endif    //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2672 
2673    void reallocate_at(size_type new_capacity, size_type buffer_offset)
2674    {
2675       pointer new_buffer = allocate(new_capacity);
2676       {
2677          allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2678          boost::container::uninitialized_move_alloc(get_allocator_ref(), this->begin(), this->end(), new_buffer + buffer_offset);
2679          new_buffer_guard.release();
2680       }
2681       destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
2682       deallocate_buffer();
2683 
2684       m_.buffer = new_buffer;
2685       //Safe cast, allocate() will handle stored_size_type overflow
2686       m_.set_capacity(new_capacity);
2687       m_.set_back_idx(size_type(m_.back_idx - m_.front_idx) + buffer_offset);
2688       m_.set_front_idx(buffer_offset);
2689 
2690       BOOST_ASSERT(invariants_ok());
2691    }
2692 
2693    template <typename ForwardIterator>
2694    iterator insert_range(const_iterator position, ForwardIterator first, ForwardIterator last)
2695    {
2696       BOOST_ASSERT(position >= begin());
2697       BOOST_ASSERT(position <= end());
2698       typedef dtl::insert_range_proxy<allocator_type, ForwardIterator> proxy_t;
2699 
2700       size_type const n = boost::container::iterator_udistance(first, last);
2701       bool prefer_move_back;
2702       if (BOOST_UNLIKELY(!n)) {
2703          return begin() + size_type(position - cbegin());
2704       }
2705       else if (position == end()) {
2706          if(back_free_capacity() >= n) // fast path
2707          {
2708             iterator r(this->end());
2709             boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_end());
2710             m_.set_back_idx(m_.back_idx + n);
2711             return r;
2712          }
2713          prefer_move_back = true;
2714       }
2715       else if (position == begin()) {
2716          if(front_free_capacity() >= n) {// secondary fast path
2717             boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->priv_raw_begin() - n);
2718             m_.set_front_idx(m_.front_idx - n);
2719             return begin();
2720          }
2721          prefer_move_back = false;
2722       }
2723       else{
2724          iterator nonconst_pos = unconst_iterator(position);
2725          prefer_move_back = should_move_back(position);
2726 
2727          if(prefer_move_back){
2728             if(back_free_capacity() >= n){
2729                boost::container::expand_forward_and_insert_nonempty_middle_alloc
2730                   ( get_allocator_ref()
2731                   , boost::movelib::to_raw_pointer(nonconst_pos)
2732                   , this->priv_raw_end()
2733                   , n, proxy_t(first));
2734                m_.set_back_idx(m_.back_idx + n);
2735                return nonconst_pos;
2736             }
2737          }
2738          else{
2739             if (front_free_capacity() >= n){
2740                boost::container::expand_backward_and_insert_nonempty_middle_alloc
2741                   ( get_allocator_ref()
2742                   , this->priv_raw_begin()
2743                   , boost::movelib::to_raw_pointer(nonconst_pos)
2744                   , n, proxy_t(first));
2745                m_.set_front_idx(m_.front_idx - n);
2746                return (nonconst_pos -= n);
2747             }
2748          }
2749       }
2750       return this->insert_range_slow_path(position, n, proxy_t(first));
2751    }
2752 
2753    template <class InsertionProxy>
2754    BOOST_CONTAINER_NOINLINE iterator insert_range_slow_path
2755       (const_iterator p, const size_type n, const InsertionProxy proxy)
2756    {
2757       size_type const back_free_cap = back_free_capacity();
2758       size_type const front_free_cap = front_free_capacity();
2759       size_type const free_cap = front_free_cap + back_free_cap;
2760       size_type const index = size_type(p - cbegin());
2761 
2762       size_type const cap = m_.capacity;
2763       //Test if enough free memory would be left
2764       if (free_cap >= n && (free_cap - n) >= cap/devector_min_free_fraction) {
2765          size_type const old_size = this->size();
2766          T* const raw_pos = const_cast<T*>(boost::movelib::to_raw_pointer(p));
2767          size_type const new_size = old_size + n;
2768          size_type const new_front_idx = (cap - new_size) / 2u;
2769 
2770          T* const raw_beg = this->priv_raw_begin();
2771          T* const new_raw_beg = raw_beg - std::ptrdiff_t(m_.front_idx - new_front_idx);
2772          m_.back_idx = 0u;
2773          m_.front_idx = 0u;
2774          boost::container::expand_backward_forward_and_insert_alloc
2775             (raw_beg, old_size, new_raw_beg, raw_pos, n, proxy, get_allocator_ref());
2776          m_.set_front_idx(new_front_idx);
2777          m_.set_back_idx(new_front_idx + new_size);
2778       }
2779       else {
2780          // reallocate
2781          const size_type new_capacity = calculate_new_capacity(m_.capacity + n);
2782          pointer new_buffer = allocate(new_capacity);
2783 
2784          // guard allocation
2785          allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2786 
2787          size_type const old_size = this->size();
2788          const size_type new_front_index = (new_capacity - old_size - n) / 2u;
2789 
2790          T* const raw_pos = const_cast<T*>(boost::movelib::to_raw_pointer(p));
2791          T* const raw_new_start = const_cast<T*>(boost::movelib::to_raw_pointer(new_buffer)) + new_front_index;
2792 
2793          boost::container::uninitialized_move_and_insert_alloc
2794             (get_allocator_ref(), this->priv_raw_begin(), raw_pos, this->priv_raw_end(), raw_new_start, n, proxy);
2795          new_buffer_guard.release();
2796 
2797          // cleanup
2798          destroy_elements(begin(), end());
2799          deallocate_buffer();
2800 
2801          // rebind members
2802          m_.set_capacity(new_capacity);
2803          m_.buffer = new_buffer;
2804          m_.set_back_idx(new_front_index + old_size + n);
2805          m_.set_front_idx(new_front_index);
2806       }
2807       return begin() + index;
2808    }
2809 
2810 
2811    template <typename Iterator>
2812    void construct_from_range(Iterator b, Iterator e)
2813    {
2814       allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
2815       boost::container::uninitialized_copy_alloc(get_allocator_ref(), b, e, m_.buffer);
2816       buffer_guard.release();
2817    }
2818 
2819    template <typename ForwardIterator>
2820    void allocate_and_copy_range(ForwardIterator first, ForwardIterator last)
2821    {
2822       size_type n = boost::container::iterator_udistance(first, last);
2823 
2824       pointer new_buffer = n ? allocate(n) : pointer();
2825       allocation_guard new_buffer_guard(new_buffer, n, get_allocator_ref());
2826       boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, new_buffer);
2827       destroy_elements(begin(), end());
2828       deallocate_buffer();
2829 
2830       m_.set_capacity(n);
2831       m_.buffer = new_buffer;
2832       m_.front_idx = 0;
2833       m_.set_back_idx(n);
2834 
2835       new_buffer_guard.release();
2836    }
2837 
2838    static void swap_big_big(devector& a, devector& b) BOOST_NOEXCEPT
2839    {
2840       boost::adl_move_swap(a.m_.capacity, b.m_.capacity);
2841       boost::adl_move_swap(a.m_.buffer, b.m_.buffer);
2842    }
2843 
2844    template <typename ForwardIterator>
2845    void overwrite_buffer_impl(ForwardIterator first, ForwardIterator last, dtl::true_)
2846    {
2847       const size_type n = boost::container::iterator_udistance(first, last);
2848 
2849       BOOST_ASSERT(m_.capacity >= n);
2850       boost::container::uninitialized_copy_alloc_n
2851             ( get_allocator_ref(), first
2852             , n, boost::movelib::to_raw_pointer(m_.buffer));
2853       m_.front_idx = 0;
2854       m_.set_back_idx(n);
2855    }
2856 
2857    template <typename InputIterator>
2858    InputIterator overwrite_buffer_impl(InputIterator first, InputIterator last, dtl::false_)
2859    {
2860       pointer pos = m_.buffer;
2861       detail::construction_guard<allocator_type> front_guard(pos, get_allocator_ref());
2862 
2863       while (first != last && pos != begin()) {
2864          this->alloc_construct(pos++, *first++);
2865          front_guard.extend();
2866       }
2867 
2868       while (first != last && pos != end()) {
2869          *pos++ = *first++;
2870       }
2871 
2872       detail::construction_guard<allocator_type> back_guard(pos, get_allocator_ref());
2873 
2874       iterator capacity_end = m_.buffer + m_.capacity;
2875       while (first != last && pos != capacity_end) {
2876          this->alloc_construct(pos++, *first++);
2877          back_guard.extend();
2878       }
2879 
2880       pointer destroy_after = dtl::min_value(dtl::max_value(begin(), pos), end());
2881       destroy_elements(destroy_after, end());
2882 
2883       front_guard.release();
2884       back_guard.release();
2885 
2886       m_.front_idx = 0;
2887       m_.set_back_idx(pos_to_index(pos));
2888       return first;
2889    }
2890 
2891    template <typename ForwardIterator>
2892    inline void overwrite_buffer(ForwardIterator first, ForwardIterator last)
2893    {
2894       this->overwrite_buffer_impl(first, last, 
2895             dtl::bool_<dtl::is_trivially_destructible<T>::value>());
2896    }
2897 
2898    bool invariants_ok()
2899    {
2900       return  (! m_.capacity || m_.buffer )
2901               && m_.front_idx <= m_.back_idx
2902               && m_.back_idx <= m_.capacity;
2903    }
2904 
2905    struct impl : allocator_type
2906    {
2907       BOOST_MOVABLE_BUT_NOT_COPYABLE(impl)
2908 
2909       public:
2910       allocator_type &get_al()
2911       {   return *this;   }
2912 
2913       static pointer do_allocate(allocator_type &a, size_type cap)
2914       {
2915          if (cap) {
2916             //First detect overflow on smaller stored_size_types
2917             if (cap > stored_size_type(-1)){
2918                   boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
2919             }
2920             return allocator_traits_type::allocate(a, cap);
2921          }
2922          else {
2923             return pointer();
2924          }
2925       }
2926 
2927       impl()
2928          : allocator_type(), buffer(), front_idx(), back_idx(), capacity()
2929          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2930          , capacity_alloc_count(0)
2931          #endif
2932       {}
2933 
2934       explicit impl(const allocator_type &a)
2935          : allocator_type(a), buffer(), front_idx(), back_idx(), capacity()
2936          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2937          , capacity_alloc_count(0)
2938          #endif
2939       {}
2940 
2941       impl(reserve_uninitialized_t, const allocator_type& a, size_type c)
2942          : allocator_type(a), buffer(do_allocate(get_al(), c) )
2943          //static cast sizes, as the allocation function will take care of overflows
2944          , front_idx(static_cast<stored_size_type>(0u))
2945          , back_idx(static_cast<stored_size_type>(c))
2946          , capacity(static_cast<stored_size_type>(c))
2947          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2948          , capacity_alloc_count(size_type(buffer != pointer()))
2949          #endif
2950       {}
2951 
2952       impl(reserve_only_tag_t, const allocator_type &a, size_type const ffc, size_type const bfc)
2953          : allocator_type(a), buffer(do_allocate(get_al(), ffc+bfc) )
2954          //static cast sizes, as the allocation function will take care of overflows
2955          , front_idx(static_cast<stored_size_type>(ffc))
2956          , back_idx(static_cast<stored_size_type>(ffc))
2957          , capacity(static_cast<stored_size_type>(ffc + bfc))
2958          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2959          , capacity_alloc_count(size_type(buffer != pointer()))
2960          #endif
2961       {}
2962 
2963       impl(reserve_only_tag_t, const allocator_type &a, size_type const c)
2964          : allocator_type(a), buffer(do_allocate(get_al(), c) )
2965          //static cast sizes, as the allocation function will take care of overflows
2966          , front_idx(static_cast<stored_size_type>(c/2u))
2967          , back_idx(static_cast<stored_size_type>(c/2u))
2968          , capacity(static_cast<stored_size_type>(c))
2969          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2970          , capacity_alloc_count(size_type(buffer != pointer()))
2971          #endif
2972       {}
2973 
2974       impl(review_implementation_t, const allocator_type &a, pointer p, size_type fi, size_type bi, size_type c)
2975          : allocator_type(a), buffer(p)
2976          //static cast sizes, as the allocation function will take care of overflows
2977          , front_idx(static_cast<stored_size_type>(fi))
2978          , back_idx(static_cast<stored_size_type>(bi))
2979          , capacity(static_cast<stored_size_type>(c))
2980          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2981          , capacity_alloc_count(0)
2982          #endif
2983       {}
2984 
2985       impl(BOOST_RV_REF(impl) m)
2986          : allocator_type(BOOST_MOVE_BASE(allocator_type, m))
2987          , buffer(static_cast<impl&>(m).buffer)
2988          , front_idx(static_cast<impl&>(m).front_idx)
2989          , back_idx(static_cast<impl&>(m).back_idx)
2990          , capacity(static_cast<impl&>(m).capacity)
2991          #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2992          , capacity_alloc_count(0)
2993          #endif
2994       {
2995          impl &i = static_cast<impl&>(m);
2996          // buffer is already acquired, reset rhs
2997          i.capacity = 0u;
2998          i.buffer = pointer();
2999          i.front_idx = 0;
3000          i.back_idx = 0;
3001       }
3002 
3003       inline void set_back_idx(size_type bi)
3004       {
3005          back_idx = static_cast<stored_size_type>(bi);
3006       }
3007 
3008       inline void set_front_idx(size_type fi)
3009       {
3010          front_idx = static_cast<stored_size_type>(fi);
3011       }
3012 
3013       inline void set_capacity(size_type c)
3014       {
3015          capacity = static_cast<stored_size_type>(c);
3016       }
3017 
3018       pointer           buffer;
3019       stored_size_type  front_idx;
3020       stored_size_type  back_idx;
3021       stored_size_type  capacity;
3022       #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3023       size_type capacity_alloc_count;
3024       #endif
3025    } m_;
3026 
3027    #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3028    public:
3029    void reset_alloc_stats()
3030    {
3031       m_.capacity_alloc_count = 0;
3032    }
3033 
3034    size_type get_alloc_count() const
3035    {
3036       return m_.capacity_alloc_count;
3037    }
3038 
3039    #endif // ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3040 
3041    #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3042 };
3043 
3044 }} // namespace boost::container
3045 
3046 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3047 
3048 namespace boost {
3049 
3050 //!has_trivial_destructor_after_move<> == true_type
3051 //!specialization for optimizations
3052 template <class T, class Allocator, class Options>
3053 struct has_trivial_destructor_after_move<boost::container::devector<T, Allocator, Options> >
3054 {
3055     typedef typename boost::container::devector<T, Allocator, Options>::allocator_type allocator_type;
3056     typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3057     BOOST_STATIC_CONSTEXPR bool value =
3058       ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3059       ::boost::has_trivial_destructor_after_move<pointer>::value;
3060 };
3061 
3062 }
3063 
3064 #endif    //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3065 
3066 #include <boost/container/detail/config_end.hpp>
3067 
3068 #endif // BOOST_CONTAINER_DEVECTOR_HPP