Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:10

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 #ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
0011 #define BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
0012 
0013 #ifndef BOOST_CONFIG_HPP
0014 #  include <boost/config.hpp>
0015 #endif
0016 
0017 #if defined(BOOST_HAS_PRAGMA_ONCE)
0018 #  pragma once
0019 #endif
0020 
0021 // container
0022 #include <boost/container/allocator_traits.hpp>
0023 // container/detail
0024 #include <boost/container/detail/iterator.hpp>
0025 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0026 #include <boost/container/detail/mpl.hpp>
0027 #include <boost/container/detail/type_traits.hpp>
0028 #include <boost/container/detail/construct_in_place.hpp>
0029 #include <boost/container/detail/destroyers.hpp>
0030 
0031 // move
0032 #include <boost/move/adl_move_swap.hpp>
0033 #include <boost/move/iterator.hpp>
0034 #include <boost/move/utility_core.hpp>
0035 #include <boost/move/traits.hpp>
0036 // other
0037 #include <boost/assert.hpp>
0038 // std
0039 #include <cstring> //for memmove/memcpy
0040 
0041 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
0042 #pragma GCC diagnostic push
0043 //pair memcpy optimizations rightfully detected by GCC
0044 #  if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
0045 #     pragma GCC diagnostic ignored "-Wclass-memaccess"
0046 #  endif
0047 //GCC 8 seems a bit confused about array access error with static_vector
0048 //when out of bound exceptions are being thrown.
0049 #  if defined(BOOST_GCC) && (BOOST_GCC >= 80000) && (BOOST_GCC < 80200)
0050 #     pragma GCC diagnostic ignored "-Wstringop-overflow"
0051 #  endif
0052 #  pragma GCC diagnostic ignored "-Warray-bounds"
0053 #endif
0054 
0055 namespace boost {
0056 namespace container {
0057 namespace dtl {
0058 
0059 template<class I>
0060 struct are_elements_contiguous
0061 {
0062    static const bool value = false;
0063 };
0064 
0065 /////////////////////////
0066 //    raw pointers
0067 /////////////////////////
0068 
0069 template<class T>
0070 struct are_elements_contiguous<T*>
0071 {
0072    static const bool value = true;
0073 };
0074 
0075 /////////////////////////
0076 //    move iterators
0077 /////////////////////////
0078 
0079 template<class It>
0080 struct are_elements_contiguous< ::boost::move_iterator<It> >
0081    : are_elements_contiguous<It>
0082 {};
0083 
0084 }  //namespace dtl {
0085 
0086 /////////////////////////
0087 //    predeclarations
0088 /////////////////////////
0089 
0090 template <class Pointer, bool IsConst>
0091 class vec_iterator;
0092 
0093 }  //namespace container {
0094 
0095 namespace interprocess {
0096 
0097 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
0098 class offset_ptr;
0099 
0100 }  //namespace interprocess {
0101 
0102 namespace container {
0103 
0104 namespace dtl {
0105 
0106 /////////////////////////
0107 //vector_[const_]iterator
0108 /////////////////////////
0109 
0110 template <class Pointer, bool IsConst>
0111 struct are_elements_contiguous<boost::container::vec_iterator<Pointer, IsConst> >
0112 {
0113    static const bool value = true;
0114 };
0115 
0116 
0117 /////////////////////////
0118 //    offset_ptr
0119 /////////////////////////
0120 
0121 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
0122 struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
0123 {
0124    static const bool value = true;
0125 };
0126 
0127 template <typename I, typename O>
0128 struct are_contiguous_and_same
0129    : boost::move_detail::and_
0130       < are_elements_contiguous<I>
0131       , are_elements_contiguous<O>
0132       , is_same< typename remove_const< typename ::boost::container::iter_value<I>::type >::type
0133                , typename ::boost::container::iterator_traits<O>::value_type
0134                >
0135       >
0136 {};
0137 
0138 template <typename I, typename O>
0139 struct is_memtransfer_copy_assignable
0140    : boost::move_detail::and_
0141       < are_contiguous_and_same<I, O>
0142       , dtl::is_trivially_copy_assignable< typename ::boost::container::iter_value<I>::type >
0143       >
0144 {};
0145 
0146 template <typename I, typename O>
0147 struct is_memtransfer_copy_constructible
0148    : boost::move_detail::and_
0149       < are_contiguous_and_same<I, O>
0150       , dtl::is_trivially_copy_constructible< typename ::boost::container::iter_value<I>::type >
0151       >
0152 {};
0153 
0154 template <typename I, typename O, typename R>
0155 struct enable_if_memtransfer_copy_constructible
0156    : enable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
0157 {};
0158 
0159 template <typename I, typename O, typename R>
0160 struct disable_if_memtransfer_copy_constructible
0161    : disable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
0162 {};
0163 
0164 template <typename I, typename O, typename R>
0165 struct enable_if_memtransfer_copy_assignable
0166    : enable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
0167 {};
0168 
0169 template <typename I, typename O, typename R>
0170 struct disable_if_memtransfer_copy_assignable
0171    : disable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
0172 {};
0173 
0174 template <class T>
0175 struct has_single_value
0176 {
0177 private:
0178    struct two { char array_[2]; };
0179    template<bool Arg> struct wrapper;
0180    template <class U> static two test(int, ...);
0181    template <class U> static char test(int, const wrapper<U::single_value>*);
0182 public:
0183    static const bool value = sizeof(test<T>(0, 0)) == 1;
0184    void dummy() {}
0185 };
0186 
0187 template<class InsertionProxy, bool = has_single_value<InsertionProxy>::value>
0188 struct is_single_value_proxy_impl
0189 {
0190    static const bool value = InsertionProxy::single_value;
0191 };
0192 
0193 template<class InsertionProxy>
0194 struct is_single_value_proxy_impl<InsertionProxy, false>
0195 {
0196    static const bool value = false;
0197 };
0198 
0199 template<class InsertionProxy>
0200 struct is_single_value_proxy
0201    : is_single_value_proxy_impl<InsertionProxy>
0202 {};
0203 
0204 template <typename P, typename R = void>
0205 struct enable_if_single_value_proxy
0206    : enable_if<is_single_value_proxy<P>, R>
0207 {};
0208 
0209 template <typename P, typename R = void>
0210 struct disable_if_single_value_proxy
0211    : disable_if<is_single_value_proxy<P>, R>
0212 {};
0213 
0214 template
0215    <typename I, // I models InputIterator
0216     typename F> // F models ForwardIterator
0217 BOOST_CONTAINER_FORCEINLINE F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0218 {
0219    typedef typename boost::container::iter_value<I>::type      value_type;
0220    typedef typename boost::container::iterator_traits<F>::difference_type r_difference_type;
0221    value_type *const dest_raw = boost::movelib::iterator_to_raw_pointer(r);
0222    const value_type *const beg_raw = boost::movelib::iterator_to_raw_pointer(f);
0223    const value_type *const end_raw = boost::movelib::iterator_to_raw_pointer(l);
0224    if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
0225       const std::size_t n = std::size_t(end_raw - beg_raw)   ;
0226       std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
0227       r += static_cast<r_difference_type>(n);
0228    }
0229    return r;
0230 }
0231 
0232 template
0233    <typename I, // I models InputIterator
0234     typename F> // F models ForwardIterator
0235 BOOST_CONTAINER_FORCEINLINE F memmove_n(I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0236 {
0237    typedef typename boost::container::iter_value<I>::type value_type;
0238    typedef typename boost::container::iterator_traits<F>::difference_type r_difference_type;
0239    if(BOOST_LIKELY(n != 0)){
0240       void *dst = boost::movelib::iterator_to_raw_pointer(r);
0241       const void *src = boost::movelib::iterator_to_raw_pointer(f);
0242       if (dst && src)
0243          std::memmove(dst, src, sizeof(value_type)*n);
0244       r += static_cast<r_difference_type>(n);
0245    }
0246 
0247    return r;
0248 }
0249 
0250 template
0251    <typename I, // I models InputIterator
0252     typename F> // F models ForwardIterator
0253 BOOST_CONTAINER_FORCEINLINE I memmove_n_source(I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0254 {
0255    if(BOOST_LIKELY(n != 0)){
0256       typedef typename boost::container::iter_value<I>::type value_type;
0257       typedef typename boost::container::iterator_traits<I>::difference_type i_difference_type;
0258       void *dst = boost::movelib::iterator_to_raw_pointer(r);
0259       const void *src = boost::movelib::iterator_to_raw_pointer(f);
0260       if (dst && src)
0261          std::memmove(dst, src, sizeof(value_type)*n);
0262       f += static_cast<i_difference_type>(n);
0263    }
0264    return f;
0265 }
0266 
0267 template
0268    <typename I, // I models InputIterator
0269     typename F> // F models ForwardIterator
0270 BOOST_CONTAINER_FORCEINLINE I memmove_n_source_dest(I f, std::size_t n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
0271 {
0272    typedef typename boost::container::iter_value<I>::type value_type;
0273    typedef typename boost::container::iterator_traits<F>::difference_type i_difference_type;
0274    typedef typename boost::container::iterator_traits<F>::difference_type f_difference_type;
0275 
0276    if(BOOST_LIKELY(n != 0)){
0277       void *dst = boost::movelib::iterator_to_raw_pointer(r);
0278       const void *src = boost::movelib::iterator_to_raw_pointer(f);
0279       if (dst && src)
0280          std::memmove(dst, src, sizeof(value_type)*n);
0281       f += i_difference_type(n);
0282       r += f_difference_type(n);
0283    }
0284    return f;
0285 }
0286 
0287 template <typename O>
0288 struct is_memzero_initializable
0289 {
0290    typedef typename ::boost::container::iterator_traits<O>::value_type value_type;
0291    static const bool value = are_elements_contiguous<O>::value &&
0292       (  dtl::is_integral<value_type>::value || dtl::is_enum<value_type>::value
0293       #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
0294       || dtl::is_pointer<value_type>::value
0295       #endif
0296       #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
0297       || dtl::is_floating_point<value_type>::value
0298       #endif
0299       );
0300 };
0301 
0302 template <typename O, typename R>
0303 struct enable_if_memzero_initializable
0304    : enable_if_c<dtl::is_memzero_initializable<O>::value, R>
0305 {};
0306 
0307 template <typename O, typename R>
0308 struct disable_if_memzero_initializable
0309    : enable_if_c<!dtl::is_memzero_initializable<O>::value, R>
0310 {};
0311 
0312 template <typename I, typename R>
0313 struct enable_if_trivially_destructible
0314    : enable_if_c < dtl::is_trivially_destructible
0315                   <typename boost::container::iter_value<I>::type>::value
0316                , R>
0317 {};
0318 
0319 template <typename I, typename R>
0320 struct disable_if_trivially_destructible
0321    : enable_if_c <!dtl::is_trivially_destructible
0322                   <typename boost::container::iter_value<I>::type>::value
0323                , R>
0324 {};
0325 
0326 }  //namespace dtl {
0327 
0328 //////////////////////////////////////////////////////////////////////////////
0329 //
0330 //                               uninitialized_move_alloc
0331 //
0332 //////////////////////////////////////////////////////////////////////////////
0333 
0334 
0335 //! <b>Effects</b>:
0336 //!   \code
0337 //!   for (; f != l; ++r, ++f)
0338 //!      allocator_traits::construct(a, &*r, boost::move(*f));
0339 //!   \endcode
0340 //!
0341 //! <b>Returns</b>: r
0342 template
0343    <typename Allocator,
0344     typename I, // I models InputIterator
0345     typename F> // F models ForwardIterator
0346 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
0347    uninitialized_move_alloc(Allocator &a, I f, I l, F r)
0348 {
0349    F back = r;
0350    BOOST_CONTAINER_TRY{
0351       while (f != l) {
0352          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
0353          ++f; ++r;
0354       }
0355    }
0356    BOOST_CONTAINER_CATCH(...){
0357       for (; back != r; ++back){
0358          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0359       }
0360       BOOST_CONTAINER_RETHROW;
0361    }
0362    BOOST_CONTAINER_CATCH_END
0363    return r;
0364 }
0365 
0366 template
0367    <typename Allocator,
0368     typename I, // I models InputIterator
0369     typename F> // F models ForwardIterator
0370 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
0371    uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0372 {  return dtl::memmove(f, l, r); }
0373 
0374 //////////////////////////////////////////////////////////////////////////////
0375 //
0376 //                               uninitialized_move_alloc_n
0377 //
0378 //////////////////////////////////////////////////////////////////////////////
0379 
0380 //! <b>Effects</b>:
0381 //!   \code
0382 //!   for (; n--; ++r, ++f)
0383 //!      allocator_traits::construct(a, &*r, boost::move(*f));
0384 //!   \endcode
0385 //!
0386 //! <b>Returns</b>: r
0387 template
0388    <typename Allocator,
0389     typename I, // I models InputIterator
0390     typename F> // F models ForwardIterator
0391 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
0392    uninitialized_move_alloc_n(Allocator &a, I f, std::size_t n, F r)
0393 {
0394    F back = r;
0395    BOOST_CONTAINER_TRY{
0396       while (n) {
0397          --n;
0398          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
0399          ++f; ++r;
0400       }
0401    }
0402    BOOST_CONTAINER_CATCH(...){
0403       for (; back != r; ++back){
0404          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0405       }
0406       BOOST_CONTAINER_RETHROW;
0407    }
0408    BOOST_CONTAINER_CATCH_END
0409    return r;
0410 }
0411 
0412 template
0413    <typename Allocator,
0414     typename I, // I models InputIterator
0415     typename F> // F models ForwardIterator
0416 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
0417    uninitialized_move_alloc_n(Allocator &, I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0418 {  return dtl::memmove_n(f, n, r); }
0419 
0420 //////////////////////////////////////////////////////////////////////////////
0421 //
0422 //                               uninitialized_move_alloc_n_source
0423 //
0424 //////////////////////////////////////////////////////////////////////////////
0425 
0426 //! <b>Effects</b>:
0427 //!   \code
0428 //!   for (; n--; ++r, ++f)
0429 //!      allocator_traits::construct(a, &*r, boost::move(*f));
0430 //!   \endcode
0431 //!
0432 //! <b>Returns</b>: f (after incremented)
0433 template
0434    <typename Allocator,
0435     typename I, // I models InputIterator
0436     typename F> // F models ForwardIterator
0437 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
0438    uninitialized_move_alloc_n_source(Allocator &a, I f, std::size_t n, F r)
0439 {
0440    F back = r;
0441    BOOST_CONTAINER_TRY{
0442       while (n) {
0443          --n;
0444          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
0445          ++f; ++r;
0446       }
0447    }
0448    BOOST_CONTAINER_CATCH(...){
0449       for (; back != r; ++back){
0450          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0451       }
0452       BOOST_CONTAINER_RETHROW;
0453    }
0454    BOOST_CONTAINER_CATCH_END
0455    return f;
0456 }
0457 
0458 template
0459    <typename Allocator,
0460     typename I, // I models InputIterator
0461     typename F> // F models ForwardIterator
0462 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
0463    uninitialized_move_alloc_n_source(Allocator &, I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0464 {  return dtl::memmove_n_source(f, n, r); }
0465 
0466 //////////////////////////////////////////////////////////////////////////////
0467 //
0468 //                               uninitialized_copy_alloc
0469 //
0470 //////////////////////////////////////////////////////////////////////////////
0471 
0472 //! <b>Effects</b>:
0473 //!   \code
0474 //!   for (; f != l; ++r, ++f)
0475 //!      allocator_traits::construct(a, &*r, *f);
0476 //!   \endcode
0477 //!
0478 //! <b>Returns</b>: r
0479 template
0480    <typename Allocator,
0481     typename I, // I models InputIterator
0482     typename F> // F models ForwardIterator
0483 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
0484    uninitialized_copy_alloc(Allocator &a, I f, I l, F r)
0485 {
0486    F back = r;
0487    BOOST_CONTAINER_TRY{
0488       while (f != l) {
0489          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
0490          ++f; ++r;
0491       }
0492    }
0493    BOOST_CONTAINER_CATCH(...){
0494       for (; back != r; ++back){
0495          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0496       }
0497       BOOST_CONTAINER_RETHROW;
0498    }
0499    BOOST_CONTAINER_CATCH_END
0500    return r;
0501 }
0502 
0503 template
0504    <typename Allocator,
0505     typename I, // I models InputIterator
0506     typename F> // F models ForwardIterator
0507 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
0508    uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0509 {  return dtl::memmove(f, l, r); }
0510 
0511 //////////////////////////////////////////////////////////////////////////////
0512 //
0513 //                               uninitialized_copy_alloc_n
0514 //
0515 //////////////////////////////////////////////////////////////////////////////
0516 
0517 //! <b>Effects</b>:
0518 //!   \code
0519 //!   for (; n--; ++r, ++f)
0520 //!      allocator_traits::construct(a, &*r, *f);
0521 //!   \endcode
0522 //!
0523 //! <b>Returns</b>: r
0524 template
0525    <typename Allocator,
0526     typename I, // I models InputIterator
0527     typename F> // F models ForwardIterator
0528 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
0529    uninitialized_copy_alloc_n(Allocator &a, I f, std::size_t n, F r)
0530 {
0531    F back = r;
0532    BOOST_CONTAINER_TRY{
0533       while (n) {
0534          --n;
0535          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
0536          ++f; ++r;
0537       }
0538    }
0539    BOOST_CONTAINER_CATCH(...){
0540       for (; back != r; ++back){
0541          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0542       }
0543       BOOST_CONTAINER_RETHROW;
0544    }
0545    BOOST_CONTAINER_CATCH_END
0546    return r;
0547 }
0548 
0549 template
0550    <typename Allocator,
0551     typename I, // I models InputIterator
0552     typename F> // F models ForwardIterator
0553 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
0554    uninitialized_copy_alloc_n(Allocator &, I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0555 {  return dtl::memmove_n(f, n, r); }
0556 
0557 //////////////////////////////////////////////////////////////////////////////
0558 //
0559 //                               uninitialized_copy_alloc_n_source
0560 //
0561 //////////////////////////////////////////////////////////////////////////////
0562 
0563 //! <b>Effects</b>:
0564 //!   \code
0565 //!   for (; n--; ++r, ++f)
0566 //!      allocator_traits::construct(a, &*r, *f);
0567 //!   \endcode
0568 //!
0569 //! <b>Returns</b>: f (after incremented)
0570 template
0571    <typename Allocator,
0572     typename I, // I models InputIterator
0573     typename F> // F models ForwardIterator
0574 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
0575    uninitialized_copy_alloc_n_source(Allocator &a, I f, std::size_t n, F r)
0576 {
0577    F back = r;
0578    BOOST_CONTAINER_TRY{
0579       while (n) {
0580          boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
0581          ++f; ++r; --n;
0582       }
0583    }
0584    BOOST_CONTAINER_CATCH(...){
0585       for (; back != r; ++back){
0586          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0587       }
0588       BOOST_CONTAINER_RETHROW;
0589    }
0590    BOOST_CONTAINER_CATCH_END
0591    return f;
0592 }
0593 
0594 template
0595    <typename Allocator,
0596     typename I, // I models InputIterator
0597     typename F> // F models ForwardIterator
0598 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
0599    uninitialized_copy_alloc_n_source(Allocator &, I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0600 {  return dtl::memmove_n_source(f, n, r); }
0601 
0602 //////////////////////////////////////////////////////////////////////////////
0603 //
0604 //                               uninitialized_value_init_alloc_n
0605 //
0606 //////////////////////////////////////////////////////////////////////////////
0607 
0608 //! <b>Effects</b>:
0609 //!   \code
0610 //!   for (; n--; ++r, ++f)
0611 //!      allocator_traits::construct(a, &*r);
0612 //!   \endcode
0613 //!
0614 //! <b>Returns</b>: r
0615 template
0616    <typename Allocator,
0617     typename F> // F models ForwardIterator
0618 inline typename dtl::disable_if_memzero_initializable<F, F>::type
0619    uninitialized_value_init_alloc_n(Allocator &a, std::size_t n, F r)
0620 {
0621    F back = r;
0622    BOOST_CONTAINER_TRY{
0623       while (n) {
0624          --n;
0625          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r));
0626          ++r;
0627       }
0628    }
0629    BOOST_CONTAINER_CATCH(...){
0630       for (; back != r; ++back){
0631          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0632       }
0633       BOOST_CONTAINER_RETHROW;
0634    }
0635    BOOST_CONTAINER_CATCH_END
0636    return r;
0637 }
0638 
0639 template
0640    <typename Allocator,
0641     typename F> // F models ForwardIterator
0642 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memzero_initializable<F, F>::type
0643    uninitialized_value_init_alloc_n(Allocator &, std::size_t n, F r)
0644 {
0645    typedef typename boost::container::iterator_traits<F>::value_type value_type;
0646    typedef typename boost::container::iterator_traits<F>::difference_type r_difference_type;
0647 
0648    if (BOOST_LIKELY(n != 0)){
0649       std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
0650       r += static_cast<r_difference_type>(n);
0651    }
0652    return r;
0653 }
0654 
0655 //////////////////////////////////////////////////////////////////////////////
0656 //
0657 //                               uninitialized_default_init_alloc_n
0658 //
0659 //////////////////////////////////////////////////////////////////////////////
0660 
0661 //! <b>Effects</b>:
0662 //!   \code
0663 //!   for (; n--; ++r, ++f)
0664 //!      allocator_traits::construct(a, &*r);
0665 //!   \endcode
0666 //!
0667 //! <b>Returns</b>: r
0668 template
0669    <typename Allocator,
0670     typename F> // F models ForwardIterator
0671 inline F uninitialized_default_init_alloc_n(Allocator &a, std::size_t n, F r)
0672 {
0673    F back = r;
0674    BOOST_CONTAINER_TRY{
0675       while (n) {
0676          --n;
0677          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init);
0678          ++r;
0679       }
0680    }
0681    BOOST_CONTAINER_CATCH(...){
0682       for (; back != r; ++back){
0683          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0684       }
0685       BOOST_CONTAINER_RETHROW;
0686    }
0687    BOOST_CONTAINER_CATCH_END
0688    return r;
0689 }
0690 
0691 //////////////////////////////////////////////////////////////////////////////
0692 //
0693 //                               uninitialized_fill_alloc
0694 //
0695 //////////////////////////////////////////////////////////////////////////////
0696 
0697 //! <b>Effects</b>:
0698 //!   \code
0699 //!   for (; f != l; ++r, ++f)
0700 //!      allocator_traits::construct(a, &*r, *f);
0701 //!   \endcode
0702 //!
0703 //! <b>Returns</b>: r
0704 template
0705    <typename Allocator,
0706     typename F, // F models ForwardIterator
0707     typename T>
0708 inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t)
0709 {
0710    F back = f;
0711    BOOST_CONTAINER_TRY{
0712       while (f != l) {
0713          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t);
0714          ++f;
0715       }
0716    }
0717    BOOST_CONTAINER_CATCH(...){
0718       for (; back != l; ++back){
0719          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0720       }
0721       BOOST_CONTAINER_RETHROW;
0722    }
0723    BOOST_CONTAINER_CATCH_END
0724 }
0725 
0726 
0727 //////////////////////////////////////////////////////////////////////////////
0728 //
0729 //                               uninitialized_fill_alloc_n
0730 //
0731 //////////////////////////////////////////////////////////////////////////////
0732 
0733 //! <b>Effects</b>:
0734 //!   \code
0735 //!   for (; n--; ++r, ++f)
0736 //!      allocator_traits::construct(a, &*r, v);
0737 //!   \endcode
0738 //!
0739 //! <b>Returns</b>: r
0740 template
0741    <typename Allocator,
0742     typename T,
0743     typename F> // F models ForwardIterator
0744 inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, std::size_t n, F r)
0745 {
0746    F back = r;
0747    BOOST_CONTAINER_TRY{
0748       while (n) {
0749          --n;
0750          allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v);
0751          ++r;
0752       }
0753    }
0754    BOOST_CONTAINER_CATCH(...){
0755       for (; back != r; ++back){
0756          allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
0757       }
0758       BOOST_CONTAINER_RETHROW;
0759    }
0760    BOOST_CONTAINER_CATCH_END
0761    return r;
0762 }
0763 
0764 //////////////////////////////////////////////////////////////////////////////
0765 //
0766 //                               copy
0767 //
0768 //////////////////////////////////////////////////////////////////////////////
0769 
0770 template
0771 <typename I,   // I models InputIterator
0772 typename F>    // F models ForwardIterator
0773 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
0774    copy(I f, I l, F r)
0775 {
0776    while (f != l) {
0777       *r = *f;
0778       ++f; ++r;
0779    }
0780    return r;
0781 }
0782 
0783 template
0784 <typename I,   // I models InputIterator
0785 typename F>    // F models ForwardIterator
0786 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
0787    copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0788 {  return dtl::memmove(f, l, r); }
0789 
0790 //////////////////////////////////////////////////////////////////////////////
0791 //
0792 //                               copy_n
0793 //
0794 //////////////////////////////////////////////////////////////////////////////
0795 
0796 template
0797 <typename I,   // I models InputIterator
0798 typename U,   // U models unsigned integral constant
0799 typename F>   // F models ForwardIterator
0800 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
0801    copy_n(I f, U n, F r)
0802 {
0803    while (n) {
0804       --n;
0805       *r = *f;
0806       ++f; ++r;
0807    }
0808    return r;
0809 }
0810 
0811 template
0812 <typename I,   // I models InputIterator
0813 typename U,   // U models unsigned integral constant
0814 typename F>   // F models ForwardIterator
0815 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
0816    copy_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0817 {  return dtl::memmove_n(f, n, r); }
0818 
0819 //////////////////////////////////////////////////////////////////////////////
0820 //
0821 //                            copy_n_source
0822 //
0823 //////////////////////////////////////////////////////////////////////////////
0824 
0825 template
0826 <typename I,   // I models InputIterator
0827 typename U,   // U models unsigned integral constant
0828 typename F>   // F models ForwardIterator
0829 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
0830    copy_n_source(I f, U n, F r)
0831 {
0832    while (n) {
0833       --n;
0834       boost::container::assign_in_place(r, f);
0835       ++f; ++r;
0836    }
0837    return f;
0838 }
0839 
0840 template
0841 <typename I,   // I models InputIterator
0842 typename F>   // F models ForwardIterator
0843 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
0844    copy_n_source(I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0845 {  return dtl::memmove_n_source(f, n, r); }
0846 
0847 //////////////////////////////////////////////////////////////////////////////
0848 //
0849 //                            copy_n_source_dest
0850 //
0851 //////////////////////////////////////////////////////////////////////////////
0852 
0853 template
0854 <typename I,   // I models InputIterator
0855 typename F>   // F models ForwardIterator
0856 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
0857    copy_n_source_dest(I f, std::size_t n, F &r)
0858 {
0859    while (n) {
0860       --n;
0861       *r = *f;
0862       ++f; ++r;
0863    }
0864    return f;
0865 }
0866 
0867 template
0868 <typename I,   // I models InputIterator
0869 typename F>   // F models ForwardIterator
0870 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
0871    copy_n_source_dest(I f, std::size_t n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
0872 {  return dtl::memmove_n_source_dest(f, n, r);  }
0873 
0874 //////////////////////////////////////////////////////////////////////////////
0875 //
0876 //                         move
0877 //
0878 //////////////////////////////////////////////////////////////////////////////
0879 
0880 template
0881 <typename I,   // I models InputIterator
0882 typename F>   // F models ForwardIterator
0883 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
0884    move(I f, I l, F r)
0885 {
0886    while (f != l) {
0887       *r = ::boost::move(*f);
0888       ++f; ++r;
0889    }
0890    return r;
0891 }
0892 
0893 template
0894 <typename I,   // I models InputIterator
0895 typename F>   // F models ForwardIterator
0896 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
0897    move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0898 {  return dtl::memmove(f, l, r); }
0899 
0900 //////////////////////////////////////////////////////////////////////////////
0901 //
0902 //                         move_n
0903 //
0904 //////////////////////////////////////////////////////////////////////////////
0905 
0906 template
0907 <typename I,   // I models InputIterator
0908 typename U,   // U models unsigned integral constant
0909 typename F>   // F models ForwardIterator
0910 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
0911    move_n(I f, U n, F r)
0912 {
0913    while (n) {
0914       --n;
0915       *r = ::boost::move(*f);
0916       ++f; ++r;
0917    }
0918    return r;
0919 }
0920 
0921 template
0922 <typename I,   // I models InputIterator
0923 typename U,   // U models unsigned integral constant
0924 typename F>   // F models ForwardIterator
0925 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
0926    move_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
0927 {  return dtl::memmove_n(f, n, r); }
0928 
0929 
0930 //////////////////////////////////////////////////////////////////////////////
0931 //
0932 //                         move_backward
0933 //
0934 //////////////////////////////////////////////////////////////////////////////
0935 
0936 template
0937 <typename I,   // I models BidirectionalIterator
0938 typename F>    // F models ForwardIterator
0939 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
0940    move_backward(I f, I l, F r)
0941 {
0942    while (f != l) {
0943       --l; --r;
0944       *r = ::boost::move(*l);
0945    }
0946    return r;
0947 }
0948 
0949 template
0950 <typename I,   // I models InputIterator
0951 typename F>   // F models ForwardIterator
0952 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
0953    move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
0954 {
0955    typedef typename boost::container::iter_value<I>::type value_type;
0956    const std::size_t n = boost::container::iterator_udistance(f, l);
0957    if (BOOST_LIKELY(n != 0)){
0958       r -= n;
0959       std::memmove((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
0960    }
0961    return r;
0962 }
0963 
0964 //////////////////////////////////////////////////////////////////////////////
0965 //
0966 //                         move_n_source_dest
0967 //
0968 //////////////////////////////////////////////////////////////////////////////
0969 
0970 template
0971 <typename I    // I models InputIterator
0972 ,typename U    // U models unsigned integral constant
0973 ,typename F>   // F models ForwardIterator
0974 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
0975    move_n_source_dest(I f, U n, F &r)
0976 {
0977    while (n) {
0978       --n;
0979       *r = ::boost::move(*f);
0980       ++f; ++r;
0981    }
0982    return f;
0983 }
0984 
0985 template
0986 <typename I    // I models InputIterator
0987 ,typename F>   // F models ForwardIterator
0988 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
0989    move_n_source_dest(I f, std::size_t n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
0990 {  return dtl::memmove_n_source_dest(f, n, r); }
0991 
0992 //////////////////////////////////////////////////////////////////////////////
0993 //
0994 //                         move_n_source
0995 //
0996 //////////////////////////////////////////////////////////////////////////////
0997 
0998 template
0999 <typename I    // I models InputIterator
1000 ,typename U    // U models unsigned integral constant
1001 ,typename F>   // F models ForwardIterator
1002 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
1003    move_n_source(I f, U n, F r)
1004 {
1005    while (n) {
1006       --n;
1007       *r = ::boost::move(*f);
1008       ++f; ++r;
1009    }
1010    return f;
1011 }
1012 
1013 template
1014 <typename I    // I models InputIterator
1015 ,typename F>   // F models ForwardIterator
1016 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
1017    move_n_source(I f, std::size_t n, F r) BOOST_NOEXCEPT_OR_NOTHROW
1018 {  return dtl::memmove_n_source(f, n, r); }
1019 
1020 template<typename F>   // F models ForwardIterator
1021 BOOST_CONTAINER_FORCEINLINE F move_forward_overlapping(F f, F l, F r)
1022 {
1023    return (f != r) ? (move)(f, l, r) : l;
1024 }
1025 
1026 template<typename B>   // B models BidirIterator
1027 BOOST_CONTAINER_FORCEINLINE B move_backward_overlapping(B f, B l, B rl)
1028 {
1029    return (l != rl) ? (move_backward)(f, l, rl) : f;
1030 }
1031 
1032 
1033 //////////////////////////////////////////////////////////////////////////////
1034 //
1035 //                               destroy_alloc_n
1036 //
1037 //////////////////////////////////////////////////////////////////////////////
1038 
1039 template
1040    <typename Allocator
1041    ,typename I   // I models InputIterator
1042    ,typename U>  // U models unsigned integral constant
1043 inline typename dtl::disable_if_trivially_destructible<I, void>::type
1044    destroy_alloc_n(Allocator &a, I f, U n)
1045 {
1046    while(n){
1047       --n;
1048       allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
1049       ++f;
1050    }
1051 }
1052 
1053 template
1054    <typename Allocator
1055    ,typename I   // I models InputIterator
1056    ,typename U>  // U models unsigned integral constant
1057 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_trivially_destructible<I, void>::type
1058    destroy_alloc_n(Allocator &, I, U)
1059 {}
1060 
1061 //////////////////////////////////////////////////////////////////////////////
1062 //
1063 //                               destroy_alloc
1064 //
1065 //////////////////////////////////////////////////////////////////////////////
1066 
1067 template
1068    <typename Allocator
1069    ,typename I>   // I models InputIterator
1070 inline typename dtl::disable_if_trivially_destructible<I, void>::type
1071    destroy_alloc(Allocator &a, I f, I l)
1072 {
1073    while(f != l){
1074       allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
1075       ++f;
1076    }
1077 }
1078 
1079 template
1080    <typename Allocator
1081    ,typename I >  // I models InputIterator
1082 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_trivially_destructible<I, void>::type
1083    destroy_alloc(Allocator &, I, I)
1084 {}
1085 
1086 //////////////////////////////////////////////////////////////////////////////
1087 //
1088 //                         deep_swap_alloc_n
1089 //
1090 //////////////////////////////////////////////////////////////////////////////
1091 
1092 template
1093    <std::size_t MaxTmpBytes
1094    ,typename Allocator
1095    ,typename F // F models ForwardIterator
1096    ,typename G // G models ForwardIterator
1097    >
1098 inline typename dtl::disable_if_memtransfer_copy_assignable<F, G, void>::type
1099    deep_swap_alloc_n( Allocator &a, F short_range_f, std::size_t  n_i, G large_range_f, std::size_t n_j)
1100 {
1101    std::size_t n = 0;
1102    for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
1103       boost::adl_move_swap(*short_range_f, *large_range_f);
1104    }
1105    boost::container::uninitialized_move_alloc_n(a, large_range_f, std::size_t(n_j - n_i), short_range_f);  // may throw
1106    boost::container::destroy_alloc_n(a, large_range_f, std::size_t(n_j - n_i));
1107 }
1108 
1109 static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
1110 
1111 template
1112    <std::size_t MaxTmpBytes
1113    ,typename Allocator
1114    ,typename F // F models ForwardIterator
1115    ,typename G // G models ForwardIterator
1116    >
1117 inline typename dtl::enable_if_c
1118    < dtl::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
1119    , void>::type
1120    deep_swap_alloc_n( Allocator &a, F short_range_f, std::size_t n_i, G large_range_f, std::size_t n_j)
1121 {
1122    typedef typename allocator_traits<Allocator>::value_type value_type;
1123    typedef typename dtl::aligned_storage
1124       <MaxTmpBytes, dtl::alignment_of<value_type>::value>::type storage_type;
1125    storage_type storage;
1126 
1127    const std::size_t n_i_bytes = sizeof(value_type)*n_i;
1128    void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f));
1129    void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f));
1130    void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage.data));
1131    std::memcpy(stora_ptr, large_ptr, n_i_bytes);
1132    std::memcpy(large_ptr, short_ptr, n_i_bytes);
1133    std::memcpy(short_ptr, stora_ptr, n_i_bytes);
1134    boost::container::iterator_uadvance(large_range_f, n_i);
1135    boost::container::iterator_uadvance(short_range_f, n_i);
1136    boost::container::uninitialized_move_alloc_n(a, large_range_f, std::size_t(n_j - n_i), short_range_f);  // may throw
1137    boost::container::destroy_alloc_n(a, large_range_f, std::size_t(n_j - n_i));
1138 }
1139 
1140 template
1141    <std::size_t MaxTmpBytes
1142    ,typename Allocator
1143    ,typename F // F models ForwardIterator
1144    ,typename G // G models ForwardIterator
1145    >
1146 inline typename dtl::enable_if_c
1147    < dtl::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
1148    , void>::type
1149    deep_swap_alloc_n( Allocator &a, F short_range_f, std::size_t n_i, G large_range_f, std::size_t n_j)
1150 {
1151    typedef typename allocator_traits<Allocator>::value_type value_type;
1152    typedef typename dtl::aligned_storage
1153       <DeepSwapAllocNMaxStorage, dtl::alignment_of<value_type>::value>::type storage_type;
1154    storage_type storage;
1155    const std::size_t sizeof_storage = sizeof(storage);
1156 
1157    std::size_t n_i_bytes = sizeof(value_type)*n_i;
1158    char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)));
1159    char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)));
1160    char *stora_ptr = static_cast<char*>(static_cast<void*>(storage.data));
1161 
1162    std::size_t szt_times = n_i_bytes/sizeof_storage;
1163    const std::size_t szt_rem = n_i_bytes%sizeof_storage;
1164 
1165    //Loop unrolling using Duff's device, as it seems it helps on some architectures
1166    const std::size_t Unroll = 4;
1167    std::size_t n = (szt_times + (Unroll-1))/Unroll;
1168    const std::size_t branch_number = (szt_times == 0)*Unroll + (szt_times % Unroll);
1169    switch(branch_number){
1170       case 4:
1171          break;
1172       case 0: do{
1173          std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1174          std::memcpy(large_ptr, short_ptr, sizeof_storage);
1175          std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1176          large_ptr += sizeof_storage;
1177          short_ptr += sizeof_storage;
1178          BOOST_FALLTHROUGH;
1179       case 3:
1180          std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1181          std::memcpy(large_ptr, short_ptr, sizeof_storage);
1182          std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1183          large_ptr += sizeof_storage;
1184          short_ptr += sizeof_storage;
1185          BOOST_FALLTHROUGH;
1186       case 2:
1187          std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1188          std::memcpy(large_ptr, short_ptr, sizeof_storage);
1189          std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1190          large_ptr += sizeof_storage;
1191          short_ptr += sizeof_storage;
1192          BOOST_FALLTHROUGH;
1193       case 1:
1194          std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1195          std::memcpy(large_ptr, short_ptr, sizeof_storage);
1196          std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1197          large_ptr += sizeof_storage;
1198          short_ptr += sizeof_storage;
1199          } while(--n);
1200    }
1201    std::memcpy(stora_ptr, large_ptr, szt_rem);
1202    std::memcpy(large_ptr, short_ptr, szt_rem);
1203    std::memcpy(short_ptr, stora_ptr, szt_rem);
1204    boost::container::iterator_uadvance(large_range_f, n_i);
1205    boost::container::iterator_uadvance(short_range_f, n_i);
1206    boost::container::uninitialized_move_alloc_n(a, large_range_f, std::size_t(n_j - n_i), short_range_f);  // may throw
1207    boost::container::destroy_alloc_n(a, large_range_f, std::size_t(n_j - n_i));
1208 }
1209 
1210 
1211 //////////////////////////////////////////////////////////////////////////////
1212 //
1213 //                         copy_assign_range_alloc_n
1214 //
1215 //////////////////////////////////////////////////////////////////////////////
1216 
1217 template
1218    <typename Allocator
1219    ,typename I // F models InputIterator
1220    ,typename O // G models OutputIterator
1221    >
1222 void copy_assign_range_alloc_n( Allocator &a, I inp_start, std::size_t n_i, O out_start, std::size_t n_o )
1223 {
1224    if (n_o < n_i){
1225       inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start);     // may throw
1226       boost::container::uninitialized_copy_alloc_n(a, inp_start, std::size_t(n_i - n_o), out_start);// may throw
1227    }
1228    else{
1229       out_start = boost::container::copy_n(inp_start, n_i, out_start);  // may throw
1230       boost::container::destroy_alloc_n(a, out_start, std::size_t(n_o - n_i));
1231    }
1232 }
1233 
1234 //////////////////////////////////////////////////////////////////////////////
1235 //
1236 //                         move_assign_range_alloc_n
1237 //
1238 //////////////////////////////////////////////////////////////////////////////
1239 
1240 template
1241    <typename Allocator
1242    ,typename I // F models InputIterator
1243    ,typename O // G models OutputIterator
1244    >
1245 void move_assign_range_alloc_n( Allocator &a, I inp_start, std::size_t n_i, O out_start, std::size_t n_o )
1246 {
1247    if (n_o < n_i){
1248       inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start);  // may throw
1249       boost::container::uninitialized_move_alloc_n(a, inp_start, std::size_t(n_i - n_o), out_start);  // may throw
1250    }
1251    else{
1252       out_start = boost::container::move_n(inp_start, n_i, out_start);  // may throw
1253       boost::container::destroy_alloc_n(a, out_start, std::size_t(n_o - n_i));
1254    }
1255 }
1256 
1257 template<class Allocator>
1258 struct array_destructor
1259 {
1260    typedef typename ::boost::container::allocator_traits<Allocator>::value_type value_type;
1261    typedef typename dtl::if_c
1262       <dtl::is_trivially_destructible<value_type>::value
1263       ,dtl::null_scoped_destructor_range<Allocator>
1264       ,dtl::scoped_destructor_range<Allocator>
1265       >::type type;
1266 };
1267 
1268 template<class Allocator>
1269 struct value_destructor
1270 {
1271    typedef typename ::boost::container::allocator_traits<Allocator>::value_type value_type;
1272    typedef typename dtl::if_c
1273       <dtl::is_trivially_destructible<value_type>::value
1274       , dtl::null_scoped_destructor<Allocator>
1275       , dtl::scoped_destructor<Allocator>
1276       >::type type;
1277 };
1278 
1279 template
1280    <typename Allocator
1281    ,typename F // F models ForwardIterator
1282    ,typename O // G models OutputIterator
1283    ,typename InsertionProxy
1284    >
1285 void uninitialized_move_and_insert_alloc
1286    ( Allocator &a
1287    , F first
1288    , F pos
1289    , F last
1290    , O d_first
1291    , std::size_t n
1292    , InsertionProxy insertion_proxy)
1293 {
1294    typedef typename array_destructor<Allocator>::type array_destructor_t;
1295 
1296    //Anti-exception rollbacks
1297    array_destructor_t new_values_destroyer(d_first, d_first, a);
1298 
1299    //Initialize with [begin(), pos) old buffer
1300    //the start of the new buffer
1301    O d_last = ::boost::container::uninitialized_move_alloc(a, first, pos, d_first);
1302    new_values_destroyer.set_end(d_last);
1303    //Initialize new objects, starting from previous point
1304    insertion_proxy.uninitialized_copy_n_and_update(a, d_last, n);
1305    d_last += n;
1306    new_values_destroyer.set_end(d_last);
1307    //Initialize from the rest of the old buffer,
1308    //starting from previous point
1309    (void) ::boost::container::uninitialized_move_alloc(a, pos, last, d_last);
1310    //All construction successful, disable rollbacks
1311    new_values_destroyer.release();
1312 }
1313 
1314 
1315 
1316 
1317 template
1318    <typename Allocator
1319    ,typename F // F models ForwardIterator
1320    ,typename InsertionProxy
1321    >
1322 typename dtl::enable_if_c<dtl::is_single_value_proxy<InsertionProxy>::value, void>::type
1323    expand_backward_and_insert_nonempty_middle_alloc
1324    ( Allocator &a
1325    , F const first
1326    , F const pos
1327    , std::size_t const
1328    , InsertionProxy insertion_proxy)
1329 {
1330    BOOST_ASSERT(first != pos);
1331  
1332    typedef typename value_destructor<Allocator>::type value_destructor_t;
1333    F aux = first;   --aux;
1334    allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(aux), boost::move(*first));
1335    value_destructor_t on_exception(a, boost::movelib::iterator_to_raw_pointer(aux));
1336    //Copy previous to last objects to the initialized end
1337    aux = first; ++aux;
1338    aux = boost::container::move(aux, pos, first);
1339    //Insert new objects in the pos
1340    insertion_proxy.copy_n_and_update(a, aux, 1u);
1341    on_exception.release();
1342 }
1343 
1344 template
1345    <typename Allocator
1346    ,typename F // F models ForwardIterator
1347    ,typename InsertionProxy
1348    >
1349 typename dtl::disable_if_c<dtl::is_single_value_proxy<InsertionProxy>::value, void>::type
1350    expand_backward_and_insert_nonempty_middle_alloc
1351    ( Allocator &a
1352    , F first
1353    , F pos
1354    , std::size_t const n
1355    , InsertionProxy insertion_proxy)
1356 {
1357    BOOST_ASSERT(first != pos);
1358    BOOST_ASSERT(n != 0);
1359 
1360    typedef typename array_destructor<Allocator>::type array_destructor_t;
1361    const std::size_t elems_before = iterator_udistance(first, pos);
1362    if(elems_before >= n){
1363       //New elements can be just copied.
1364       //Move to uninitialized memory last objects
1365       F const first_less_n = first - n;
1366       F nxt = ::boost::container::uninitialized_move_alloc_n_source(a, first, n, first_less_n);
1367       array_destructor_t on_exception(first_less_n, first, a);
1368       //Copy previous to last objects to the initialized end
1369       nxt = boost::container::move(nxt, pos, first);
1370       //Insert new objects in the pos
1371       insertion_proxy.copy_n_and_update(a, nxt, n);
1372       on_exception.release();
1373    }
1374    else {
1375       //The new elements don't fit in the [pos, end()) range.
1376       //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
1377       F aux = ::boost::container::uninitialized_move_alloc(a, first, pos, first - n);
1378       array_destructor_t on_exception(first -n, aux, a);
1379       //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
1380       insertion_proxy.uninitialized_copy_n_and_update(a, aux, std::size_t(n - elems_before));
1381       insertion_proxy.copy_n_and_update(a, first, elems_before);
1382       on_exception.release();
1383    }
1384 }
1385 
1386 
1387 template
1388    <typename Allocator
1389    ,typename F // F models ForwardIterator
1390    ,typename InsertionProxy
1391    >
1392 typename dtl::enable_if_c<dtl::is_single_value_proxy<InsertionProxy>::value, void>::type
1393    expand_forward_and_insert_nonempty_middle_alloc
1394    ( Allocator &a
1395    , F pos
1396    , F last
1397    , std::size_t const
1398    , InsertionProxy insertion_proxy)
1399 {
1400    BOOST_ASSERT(last != pos);
1401  
1402    typedef typename value_destructor<Allocator>::type value_destructor_t;
1403    F last_m_n = last;   --last_m_n;
1404    allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(last), boost::move(*last_m_n));
1405    value_destructor_t on_exception(a, boost::movelib::iterator_to_raw_pointer(last));
1406    //Copy previous to last objects to the initialized end
1407    boost::container::move_backward(pos, last_m_n, last);
1408    //Insert new objects in the pos
1409    insertion_proxy.copy_n_and_update(a, pos, 1);
1410    on_exception.release();
1411 }
1412 
1413 template
1414    <typename Allocator
1415    ,typename F // F models ForwardIterator
1416    ,typename InsertionProxy
1417    >
1418 typename dtl::disable_if_c<dtl::is_single_value_proxy<InsertionProxy>::value, void>::type
1419    expand_forward_and_insert_nonempty_middle_alloc
1420    ( Allocator &a
1421    , F pos
1422    , F last
1423    , std::size_t const n
1424    , InsertionProxy insertion_proxy)
1425 {
1426    BOOST_ASSERT(last != pos);
1427    BOOST_ASSERT(n != 0);
1428 
1429    typedef typename array_destructor<Allocator>::type array_destructor_t;
1430    const std::size_t elems_after = iterator_udistance(pos, last);
1431    if(elems_after >= n){
1432       //New elements can be just copied.
1433       //Move to uninitialized memory last objects
1434       F const last_m_n = last - n;
1435       F const nxt = ::boost::container::uninitialized_move_alloc_n(a, last_m_n, n, last);
1436       array_destructor_t on_exception(last, nxt, a);
1437       //Copy previous to last objects to the initialized end
1438       boost::container::move_backward(pos, last_m_n, last);
1439       //Insert new objects in the pos
1440       insertion_proxy.copy_n_and_update(a, pos, n);
1441       on_exception.release();
1442    }
1443    else {
1444       //The new elements don't fit in the [pos, end()) range.
1445       //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
1446       F new_last = ::boost::container::uninitialized_move_alloc(a, pos, last, pos + n);
1447       array_destructor_t on_exception(pos + n, new_last, a);
1448       //Copy first new elements in pos (gap is still there)
1449       insertion_proxy.copy_n_and_update(a, pos, elems_after);
1450       //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
1451       insertion_proxy.uninitialized_copy_n_and_update(a, last, std::size_t(n - elems_after));
1452       on_exception.release();
1453    }
1454 }
1455 
1456 template
1457 <typename Allocator
1458    , typename F // F models ForwardIterator
1459    , typename InsertionProxy
1460 >
1461 BOOST_CONTAINER_FORCEINLINE void expand_forward_and_insert_alloc
1462    ( Allocator& a
1463    , F pos
1464    , F last
1465    , std::size_t const n
1466    , InsertionProxy insertion_proxy)
1467 {
1468    if (last == pos) {
1469       insertion_proxy.uninitialized_copy_n_and_update(a, last, n);
1470    }
1471    else{
1472       const bool single_value = dtl::is_single_value_proxy<InsertionProxy>::value;
1473       BOOST_IF_CONSTEXPR(!single_value){
1474          if (BOOST_UNLIKELY(!n)) {
1475             return;
1476          }
1477       }
1478       expand_forward_and_insert_nonempty_middle_alloc(a, pos, last, n, insertion_proxy);
1479    }
1480 }
1481 
1482 template <class B, class InsertionProxy, class Allocator>
1483 void expand_backward_forward_and_insert_alloc_move_backward
1484 ( B const old_start
1485 , std::size_t const old_size
1486 , B const new_start
1487 , B const pos
1488 , std::size_t const n
1489 , InsertionProxy insertion_proxy
1490 , Allocator& a)
1491 {
1492    typedef std::size_t size_type;
1493    typedef typename allocator_traits<Allocator>::value_type value_type;
1494    static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<value_type>::value;
1495    static const bool trivial_dctr = dtl::is_trivially_destructible<value_type>::value;
1496 
1497    typedef typename dtl::if_c
1498       <trivial_dctr
1499       , dtl::null_scoped_destructor_n<Allocator, B>
1500       , dtl::scoped_destructor_n<Allocator, B>
1501       >::type   array_destructor_t;
1502 
1503    //n can be zero to just expand capacity
1504    B old_finish = make_iterator_uadvance(old_start, old_size);
1505 
1506    //We can have 8 possibilities:
1507    const size_type elemsbefore = static_cast<size_type>(iterator_udistance(old_start, pos));
1508    const size_type raw_before  = static_cast<size_type>(iterator_udistance(new_start, old_start));
1509    const size_type before_plus_new = size_type(elemsbefore + n);
1510 
1511    //Check if raw_before is big enough to hold the beginning of old data + new data
1512    if (raw_before >= before_plus_new) {
1513       //If anything goes wrong, this object will destroy
1514       //all the old objects to fulfill previous vector state
1515       array_destructor_t old_values_destroyer(old_start, a, old_size);
1516       // _________________________________________________________
1517       //|            raw_mem                | old_begin | old_end |  //Old situation
1518       //| __________________________________|___________|_________|
1519       // _________________________________________________________
1520       //| old_begin |    new   |  raw_mem   | old_begin | old_end |  //First step
1521       //|___________|__________|____________|___________|_________|
1522 
1523       //Copy first old values before pos, after that the new objects
1524       B const new_elem_pos = ::boost::container::uninitialized_move_alloc(a, old_start, pos, new_start);
1525       array_destructor_t new_values_destroyer(new_start, a, elemsbefore);
1526       insertion_proxy.uninitialized_copy_n_and_update(a, new_elem_pos, n);
1527       new_values_destroyer.set_size(before_plus_new);
1528       const size_type new_size = size_type(old_size + n);
1529       //Check if raw_before is so big that even copying the old data + new data
1530       //there is a gap between the new data and the old data
1531       if (raw_before >= new_size) {
1532          // _______________________________________________________
1533          //|            raw_mem              | old_begin | old_end | //Old situation
1534          //|_________________________________|___________|_________|
1535          // _______________________________________________________
1536          //| old_begin |   new  |  raw_mem   | old_begin | old_end | //First step
1537          //|___________|________|____________|___________|_________|
1538          // _______________________________________________________
1539          //| old_begin |   new  | old_end |       raw_mem          | //New situation
1540          //|___________|________|_________|________________________|
1541          //
1542          //Now initialize the rest of memory with the last old values
1543          if (before_plus_new != new_size) { //Special case to avoid operations in back insertion
1544             B new_start_end(make_iterator_uadvance(new_start, before_plus_new));
1545             ::boost::container::uninitialized_move_alloc(a, pos, old_finish, new_start_end);
1546          }
1547          //All new elements correctly constructed, avoid new element destruction
1548          new_values_destroyer.release();
1549          //Old values destroyed automatically with "old_values_destroyer"
1550          //when "old_values_destroyer" goes out of scope unless the have trivial
1551          //destructor after move.
1552          if(trivial_dctr_after_move)
1553             old_values_destroyer.release();
1554       }
1555       //raw_before is so big that divides old_end
1556       else {
1557          // _________________________________________________
1558          //|               raw           | old_beg | old_end | //Old situation
1559          //|_____________________________|_________|_________|
1560          // _________________________________________________
1561          //| old_begin |    new   |  raw | old_beg | old_end | //First step
1562          //|___________|__________|______|_________|_________|
1563          // _________________________________________________
1564          //| old_begin |    new   | old_end |  raw_mem       | //New situation
1565          //|___________|__________|_________|________________|
1566 
1567          //Now initialize the rest of memory with the last old values
1568          //All new elements correctly constructed, avoid new element destruction
1569          BOOST_IF_CONSTEXPR(!trivial_dctr) {
1570             //Now initialize the rest of raw_before memory with the
1571             //first of elements after new values
1572             const size_type raw_gap = raw_before - before_plus_new;
1573             B new_start_plus(make_iterator_uadvance(new_start, before_plus_new));
1574             ::boost::container::uninitialized_move_alloc_n(a, pos, raw_gap, new_start_plus);
1575             new_values_destroyer.release();
1576             old_values_destroyer.increment_size_backwards(raw_before);
1577             //Now move remaining last objects in the old buffer begin
1578             B remaining_pos(make_iterator_uadvance(pos, raw_gap));
1579             remaining_pos = ::boost::container::move_forward_overlapping(remaining_pos, old_finish, old_start);
1580             (void)remaining_pos;
1581             //Once moved, avoid calling the destructors if trivial after move
1582             if(!trivial_dctr_after_move) {
1583                boost::container::destroy_alloc(a, remaining_pos, old_finish);
1584             }
1585          }
1586          else { //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
1587             ::boost::container::uninitialized_move_alloc_n
1588                (a, pos, static_cast<size_type>(old_finish - pos), make_iterator_uadvance(new_start, before_plus_new));
1589          }
1590          old_values_destroyer.release();
1591       }
1592    }
1593    else {
1594       //If anything goes wrong, this object will destroy
1595       //all the old objects to fulfill previous vector state
1596       array_destructor_t old_values_destroyer(old_start, a, old_size);
1597 
1598       //Check if we have to do the insertion in two phases
1599       //since maybe raw_before is not big enough and
1600       //the buffer was expanded both sides
1601       // _________________________________________________
1602       //| raw_mem | old_begin + old_end |  raw_mem        | //Old situation
1603       //|_________|_____________________|_________________|
1604       // _________________________________________________
1605       //|     old_begin + new + old_end     |  raw_mem    | //New situation with do_after
1606       //|___________________________________|_____________|
1607       // _________________________________________________
1608       //| old_begin + new + old_end  |  raw_mem           | //New without do_after
1609       //|____________________________|____________________|
1610       //
1611       const bool do_after = n > raw_before;
1612 
1613       //Now we can have two situations: the raw_mem of the
1614       //beginning divides the old_begin, or the new elements:
1615       if (raw_before <= elemsbefore) {
1616          //The raw memory divides the old_begin group:
1617          //
1618          //If we need two phase construction (do_after)
1619          //new group is divided in new = new_beg + new_end groups
1620          //In this phase only new_beg will be inserted
1621          //
1622          // _________________________________________________
1623          //| raw_mem | old_begin | old_end |  raw_mem        | //Old situation
1624          //|_________|___________|_________|_________________|
1625          // _________________________________________________
1626          //| old_begin | new_beg | old_end |  raw_mem        | //New situation with do_after(1),
1627          //|___________|_________|_________|_________________| //not definitive, pending operations
1628          // _________________________________________________
1629          //| old_begin | new | old_end |  raw_mem            | //New situation without do_after,
1630          //|___________|_____|_________|_____________________| //definitive.
1631          //
1632          //Copy the first part of old_begin to raw_mem
1633          ::boost::container::uninitialized_move_alloc_n(a, old_start, raw_before, new_start);
1634          //The buffer is all constructed until old_end,
1635          //so program trailing destruction and assign final size
1636          //if !do_after, raw_before+n otherwise.
1637          size_type new_1st_range;
1638          old_values_destroyer.increment_size_backwards(raw_before);
1639          new_1st_range = do_after ? raw_before : n;
1640 
1641          //Now copy the second part of old_begin overwriting itself
1642          B const old_next(make_iterator_uadvance(old_start, raw_before));
1643          B const next = ::boost::container::move(old_next, pos, old_start);
1644          //Now copy the new_beg elements
1645          insertion_proxy.copy_n_and_update(a, next, new_1st_range);
1646 
1647          //If there is no after work and the last old part needs to be moved to front, do it
1648          if (!do_after) {
1649             //Now displace old_end elements and destroy trailing
1650             B const new_first(make_iterator_uadvance(next, new_1st_range));
1651             B const p = ::boost::container::move_forward_overlapping(pos, old_finish, new_first);
1652             (void)p;
1653             if(!trivial_dctr_after_move)
1654                boost::container::destroy_alloc(a, p, old_finish);
1655          }
1656       }
1657       else {
1658          //If we have to expand both sides,
1659          //we will play if the first new values so
1660          //calculate the upper bound of new values
1661 
1662          //The raw memory divides the new elements
1663          //
1664          //If we need two phase construction (do_after)
1665          //new group is divided in new = new_beg + new_end groups
1666          //In this phase only new_beg will be inserted
1667          //
1668          // ____________________________________________________
1669          //|   raw_mem     | old_begin | old_end |  raw_mem     | //Old situation
1670          //|_______________|___________|_________|______________|
1671          // ____________________________________________________
1672          //| old_begin |    new_beg    | old_end |  raw_mem     | //New situation with do_after(),
1673          //|___________|_______________|_________|______________| //not definitive, pending operations
1674          // ____________________________________________________
1675          //| old_begin | new | old_end |  raw_mem               | //New situation without do_after,
1676          //|___________|_____|_________|________________________| //definitive
1677          //
1678          //First copy whole old_begin and part of new to raw_mem
1679          B const new_pos = ::boost::container::uninitialized_move_alloc(a, old_start, pos, new_start);
1680          array_destructor_t new_values_destroyer(new_start, a, elemsbefore);
1681          const size_type mid_n = size_type(raw_before - elemsbefore);
1682          insertion_proxy.uninitialized_copy_n_and_update(a, new_pos, mid_n);
1683          new_values_destroyer.release();
1684          //The buffer is all constructed until old_end
1685          old_values_destroyer.increment_size_backwards(raw_before);
1686 
1687          if (do_after) {
1688             //Copy new_beg part
1689             insertion_proxy.copy_n_and_update(a, old_start, elemsbefore);
1690          }
1691          else {
1692             //Copy all new elements
1693             const size_type rest_new = size_type(n - mid_n);
1694             insertion_proxy.copy_n_and_update(a, old_start, rest_new);
1695 
1696             B move_start(make_iterator_uadvance(old_start, rest_new));
1697 
1698             //Displace old_end, but make sure data has to be moved
1699             B const move_end = ::boost::container::move_forward_overlapping(pos, old_finish, move_start);
1700             (void)move_end;   //To avoid warnings of unused initialization for move_end in case
1701                               //trivial_dctr_after_move is true
1702             //Destroy remaining moved elements from old_end except if they
1703             //have trivial destructor after being moved
1704             if(!trivial_dctr_after_move) {
1705                boost::container::destroy_alloc(a, move_end, old_finish);
1706             }
1707          }
1708       }
1709 
1710       //This is only executed if two phase construction is needed
1711       if (do_after) {
1712          //The raw memory divides the new elements
1713          // ______________________________________________________
1714          //|   raw_mem    | old_begin |  old_end   |  raw_mem     |  //Old situation
1715          //|______________|___________|____________|______________|
1716          // _______________________________________________________
1717          //| old_begin   +   new_beg  | new_end |old_end | rawmem |  //New situation with do_after(1)
1718          //|__________________________|_________|________|________|
1719          // ______________________________________________________
1720          //| old_begin      +       new            | old_end |raw |  //New situation with do_after(2)
1721          //|_______________________________________|_________|____|
1722          const size_type n_after = size_type(n - raw_before);
1723          const size_type elemsafter = size_type(old_size - elemsbefore);
1724 
1725          //We can have two situations:
1726          if (elemsafter >= n_after) {
1727             //The raw_mem from end will divide displaced old_end
1728             //
1729             //Old situation:
1730             // ______________________________________________________
1731             //|   raw_mem    | old_begin |  old_end   |  raw_mem     |
1732             //|______________|___________|____________|______________|
1733             //
1734             //New situation with do_after(1):
1735             // _______________________________________________________
1736             //| old_begin   +   new_beg  | new_end |old_end | raw_mem |
1737             //|__________________________|_________|________|_________|
1738             //
1739             //First copy the part of old_end raw_mem
1740             B finish_n = make_iterator_advance(old_finish, -std::ptrdiff_t(n_after));
1741             ::boost::container::uninitialized_move_alloc(a, finish_n, old_finish, old_finish);
1742             old_values_destroyer.increment_size(n_after);
1743             //Displace the rest of old_end to the new position
1744             boost::container::move_backward_overlapping(pos, finish_n, old_finish);
1745             //Now overwrite with new_end
1746             //The new_end part is [first + (n - n_after), last)
1747             insertion_proxy.copy_n_and_update(a, pos, n_after);
1748          }
1749          else {
1750             //The raw_mem from end will divide new_end part
1751             // _____________________________________________________________
1752             //|   raw_mem    | old_begin |  old_end   |  raw_mem            | //Old situation
1753             //|______________|___________|____________|_____________________|
1754             // _____________________________________________________________
1755             //| old_begin   +   new_beg  |     new_end   |old_end | raw_mem | //New situation with do_after(2)
1756             //|__________________________|_______________|________|_________|
1757 
1758             //First initialize data in raw memory
1759             const size_type mid_last_dist = size_type(n_after - elemsafter);
1760 
1761             //Copy to the old_end part to the uninitialized zone leaving a gap.
1762             B const mid_last(make_iterator_uadvance(old_finish, mid_last_dist));
1763             ::boost::container::uninitialized_move_alloc(a, pos, old_finish, mid_last);
1764 
1765             array_destructor_t old_end_destroyer(mid_last, a, iterator_udistance(pos, old_finish));
1766 
1767             //Copy the first part to the already constructed old_end zone
1768             insertion_proxy.copy_n_and_update(a, pos, elemsafter);
1769             //Copy the rest to the uninitialized zone filling the gap
1770             insertion_proxy.uninitialized_copy_n_and_update(a, old_finish, mid_last_dist);
1771             old_end_destroyer.release();
1772          }
1773       }
1774       old_values_destroyer.release();
1775    }
1776 }
1777 
1778 template
1779 <typename Allocator
1780    , typename B // B models BidirIterator
1781    , typename InsertionProxy
1782 >
1783 BOOST_CONTAINER_FORCEINLINE void expand_backward_forward_and_insert_alloc_move_forward
1784    ( B const old_start
1785    , std::size_t const old_size
1786    , B const new_start
1787    , B const pos
1788    , std::size_t const n
1789    , InsertionProxy insertion_proxy
1790    , Allocator& a)
1791 {
1792    typedef std::size_t size_type;
1793    typedef typename allocator_traits<Allocator>::value_type value_type;
1794    static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<value_type>::value;
1795    static const bool trivial_dctr = dtl::is_trivially_destructible<value_type>::value;
1796 
1797    typedef typename dtl::if_c
1798       <trivial_dctr
1799       , dtl::null_scoped_destructor_n<Allocator, B>
1800       , dtl::scoped_destructor_n<Allocator, B>
1801       >::type   array_destructor_t;
1802 
1803    //n can be zero to just expand capacity
1804 
1805    B const old_finish = make_iterator_uadvance(old_start, old_size);
1806    const size_type new_size = size_type(old_size + n);
1807    B const new_finish = make_iterator_uadvance(new_start, new_size);
1808 
1809    //We can have 8 possibilities:
1810 
1811    const size_type elemsafter = static_cast<size_type>(iterator_udistance(pos, old_finish));
1812    const size_type raw_after = static_cast<size_type>(iterator_udistance(old_finish, new_finish));
1813 
1814    const size_type after_plus_new = size_type(elemsafter + n);
1815 
1816    //Check if raw_before is big enough to hold the new data + the end of old data
1817    if (raw_after >= after_plus_new) {
1818       //If anything goes wrong, this object will destroy
1819       //all the old objects to fulfill previous vector state
1820       array_destructor_t old_values_destroyer(old_start, a, old_size);
1821       //______________________ __________________________________
1822       //| old_begin | old_end |            raw_mem                  //Old situation
1823       //|___________|_________|__________________________________
1824       // _____________________ _________________________________
1825       //| old_begin | old_end |  raw_mem |    new   |  old_end  |  //First step
1826       //|___________|_________|__________|__________|___________|
1827 
1828       //Copy first new objects, after that old values after pos
1829       B new_elem_pos = new_finish - after_plus_new;
1830       insertion_proxy.uninitialized_copy_n_and_update(a, new_elem_pos, n);
1831       array_destructor_t new_values_destroyer(new_elem_pos, a, n);
1832       ::boost::container::uninitialized_move_alloc(a, pos, old_finish, new_elem_pos+n);
1833       new_values_destroyer.set_size(after_plus_new);
1834 
1835       //Check if raw_before is so big that even copying the old data + new data
1836       //there is a gap between the new data and the old data
1837       if (raw_after >= new_size) {
1838          //______________________ __________________________________
1839          //| old_begin | old_end |            raw_mem                  //Old situation
1840          //|___________|_________|__________________________________
1841          // _____________________ _________________________________
1842          //| old_begin | old_end |    raw_mem   |   new  | old_end |  //First step
1843          //|___________|_________|______________|________|_________|
1844          // _____________________V_________________________________
1845          //|       raw_mem          | old_begin |   new  | old_end | //New situation
1846          //|________________________|___________|________|_________|
1847          //
1848          //Now initialize the rest of memory with the last old values
1849          ::boost::container::uninitialized_move_alloc(a, old_start, pos, new_start);
1850          //All new elements correctly constructed, avoid new element destruction
1851          new_values_destroyer.release();
1852          //Old values destroyed automatically with "old_values_destroyer"
1853          //when "old_values_destroyer" goes out of scope unless the have trivial
1854          //destructor after move.
1855          if(trivial_dctr_after_move)
1856             old_values_destroyer.release();
1857       }
1858       //raw_before is so big that divides old_end
1859       else {
1860          //______________________ ____________________________
1861          //| old_begin | old_end |          raw_mem             //Old situation
1862          //|___________|_________|____________________________
1863          // _____________________ ____________________________
1864          //| old_begin | old_end | raw_mem |   new  | old_end | //First step
1865          //|___________|_________|_________|________|_________|
1866          // _________________________________________________
1867          //|       raw_mem     | old_begin |   new  | old_end | //New situation
1868          //|___________________|___________|________|_________|
1869 
1870          //Now initialize the rest of raw_before memory with the
1871          //last elements before new values
1872          const size_type raw_gap = raw_after - after_plus_new;
1873          B const pre_pos_raw = pos - raw_gap;
1874          ::boost::container::uninitialized_move_alloc_n(a, pre_pos_raw, raw_gap, old_finish);
1875          new_values_destroyer.release();
1876          old_values_destroyer.increment_size(raw_after);
1877          //Now move remaining last objects in the old buffer begin
1878          BOOST_ASSERT(old_start != old_finish);
1879          boost::container::move_backward_overlapping(old_start, pre_pos_raw, old_finish);
1880          old_values_destroyer.release();
1881          if (!trivial_dctr_after_move) {
1882             boost::container::destroy_alloc(a, old_start, new_start);
1883          }
1884       }
1885    }
1886    else{
1887       //If anything goes wrong, this object will destroy
1888       //all the old objects to fulfill previous vector state
1889       array_destructor_t old_values_destroyer(old_start, a, old_size);
1890 
1891       //Now we can have two situations: the raw_mem of the
1892       //end divides the new elements or the old_end
1893       if (raw_after > elemsafter) {
1894          //The raw memory divides the new elements
1895          //__________________________________
1896          //| old_begin | old_end |    raw    |  //Old situation
1897          //|___________|_________|___________|
1898          // _____ ___________________________
1899          //| raw | old_begin | new | old_end |  //New situation
1900          //|_____|___________|_____|_________|
1901 
1902          //First copy whole old_end and part of new to raw_mem
1903          B p = new_finish - elemsafter;
1904          ::boost::container::uninitialized_move_alloc(a, pos, old_finish, p);
1905          array_destructor_t new_values_destroyer(p, a, elemsafter);
1906          //Copy all new elements
1907          const size_type mid_n = size_type(raw_after - elemsafter);
1908          const size_type rest_new = size_type(n - mid_n);
1909          B new_rng_start = old_finish - rest_new;
1910          insertion_proxy.copy_n_and_update(a, new_rng_start, rest_new);
1911          insertion_proxy.uninitialized_copy_n_and_update(a, old_finish, mid_n);
1912          new_values_destroyer.release();
1913          old_values_destroyer.increment_size_backwards(raw_after);
1914          //Displace old_end, but make sure data has to be moved
1915          p = ::boost::container::move_backward_overlapping(old_start, pos, new_rng_start);
1916 
1917          //Destroy remaining moved elements from old_begin except if they
1918          //have trivial destructor after being moved
1919          old_values_destroyer.release();
1920          if (!trivial_dctr_after_move) {
1921             boost::container::destroy_alloc(a, old_start, p);
1922          }
1923       }
1924       else {
1925          //The raw memory divides the old_end group:
1926          //________________________________________
1927          //| old_begin |    old_end    |      raw  |  //Old situation
1928          //|___________|_______________|___________|
1929          // _____ __________________________________
1930          //| raw | old_begin | new |    old_end    |  //New situation
1931          //|_____|___________|_____|_______________|
1932          //
1933          //Copy the last part of old_end to raw_mem
1934          const B old_end_pivot = old_finish - raw_after;
1935          ::boost::container::uninitialized_move_alloc_n(a, old_end_pivot, raw_after, old_finish);
1936          //The buffer is all constructed
1937          old_values_destroyer.increment_size_backwards(raw_after);
1938 
1939          //Now copy the first part of old_end overwriting itself
1940          B const new_end_pos = ::boost::container::move_backward_overlapping(pos, old_end_pivot, old_finish);
1941          B const new_beg_pos = new_end_pos - n;
1942 
1943          //Now copy the new_beg elements
1944          insertion_proxy.copy_n_and_update(a, new_beg_pos, n);
1945          B const p = ::boost::container::move_backward_overlapping(old_start, pos, new_beg_pos);
1946          old_values_destroyer.release();
1947 
1948          if (!trivial_dctr_after_move) {
1949             (void)p;
1950             boost::container::destroy_alloc(a, old_start, p);
1951          }
1952       }
1953    }
1954 }
1955 
1956 template <class R, class InsertionProxy, class Allocator>
1957 void expand_backward_forward_and_insert_alloc
1958    ( R const old_start
1959    , std::size_t const old_size
1960    , R const new_start
1961    , R const pos
1962    , std::size_t const n
1963    , InsertionProxy insertion_proxy
1964    , Allocator& a)
1965 {
1966    if(new_start < old_start){
1967       expand_backward_forward_and_insert_alloc_move_backward(old_start, old_size, new_start, pos, n, insertion_proxy, a);
1968    }
1969    else{
1970       expand_backward_forward_and_insert_alloc_move_forward(old_start, old_size, new_start, pos, n, insertion_proxy, a);
1971    }
1972 }
1973 
1974 }  //namespace container {
1975 }  //namespace boost {
1976 
1977 //#pragma GCC diagnostic ignored "-Wclass-memaccess"
1978 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
1979 #pragma GCC diagnostic pop
1980 #endif
1981 
1982 #endif   //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP