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