File indexing completed on 2025-01-18 09:30:10
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 # 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
0067
0068
0069 template<class T>
0070 struct are_elements_contiguous<T*>
0071 {
0072 static const bool value = true;
0073 };
0074
0075
0076
0077
0078
0079 template<class It>
0080 struct are_elements_contiguous< ::boost::move_iterator<It> >
0081 : are_elements_contiguous<It>
0082 {};
0083
0084 }
0085
0086
0087
0088
0089
0090 template <class Pointer, bool IsConst>
0091 class vec_iterator;
0092
0093 }
0094
0095 namespace interprocess {
0096
0097 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
0098 class offset_ptr;
0099
0100 }
0101
0102 namespace container {
0103
0104 namespace dtl {
0105
0106
0107
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
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,
0216 typename F>
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,
0234 typename F>
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,
0252 typename F>
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,
0269 typename F>
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 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 template
0343 <typename Allocator,
0344 typename I,
0345 typename F>
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,
0369 typename F>
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
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 template
0388 <typename Allocator,
0389 typename I,
0390 typename F>
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,
0415 typename F>
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
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433 template
0434 <typename Allocator,
0435 typename I,
0436 typename F>
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,
0461 typename F>
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
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 template
0480 <typename Allocator,
0481 typename I,
0482 typename F>
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,
0506 typename F>
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
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 template
0525 <typename Allocator,
0526 typename I,
0527 typename F>
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,
0552 typename F>
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
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 template
0571 <typename Allocator,
0572 typename I,
0573 typename F>
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,
0597 typename F>
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
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 template
0616 <typename Allocator,
0617 typename F>
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>
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
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668 template
0669 <typename Allocator,
0670 typename F>
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
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704 template
0705 <typename Allocator,
0706 typename F,
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
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740 template
0741 <typename Allocator,
0742 typename T,
0743 typename F>
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
0767
0768
0769
0770 template
0771 <typename I,
0772 typename F>
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,
0785 typename F>
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
0793
0794
0795
0796 template
0797 <typename I,
0798 typename U,
0799 typename F>
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,
0813 typename U,
0814 typename F>
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
0822
0823
0824
0825 template
0826 <typename I,
0827 typename U,
0828 typename F>
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,
0842 typename F>
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
0850
0851
0852
0853 template
0854 <typename I,
0855 typename F>
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,
0869 typename F>
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
0877
0878
0879
0880 template
0881 <typename I,
0882 typename F>
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,
0895 typename F>
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
0903
0904
0905
0906 template
0907 <typename I,
0908 typename U,
0909 typename F>
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,
0923 typename U,
0924 typename F>
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
0933
0934
0935
0936 template
0937 <typename I,
0938 typename F>
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,
0951 typename F>
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
0967
0968
0969
0970 template
0971 <typename I
0972 ,typename U
0973 ,typename F>
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
0987 ,typename F>
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
0995
0996
0997
0998 template
0999 <typename I
1000 ,typename U
1001 ,typename F>
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
1015 ,typename F>
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>
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>
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
1036
1037
1038
1039 template
1040 <typename Allocator
1041 ,typename I
1042 ,typename U>
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
1056 ,typename U>
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
1064
1065
1066
1067 template
1068 <typename Allocator
1069 ,typename I>
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 >
1082 BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_trivially_destructible<I, void>::type
1083 destroy_alloc(Allocator &, I, I)
1084 {}
1085
1086
1087
1088
1089
1090
1091
1092 template
1093 <std::size_t MaxTmpBytes
1094 ,typename Allocator
1095 ,typename F
1096 ,typename G
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);
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);
1110
1111 template
1112 <std::size_t MaxTmpBytes
1113 ,typename Allocator
1114 ,typename F
1115 ,typename G
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);
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
1144 ,typename G
1145 >
1146 inline typename dtl::enable_if_c
1147 < dtl::is_memtransfer_copy_assignable<F, G>::value && true
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
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);
1207 boost::container::destroy_alloc_n(a, large_range_f, std::size_t(n_j - n_i));
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217 template
1218 <typename Allocator
1219 ,typename I
1220 ,typename O
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);
1226 boost::container::uninitialized_copy_alloc_n(a, inp_start, std::size_t(n_i - n_o), out_start);
1227 }
1228 else{
1229 out_start = boost::container::copy_n(inp_start, n_i, out_start);
1230 boost::container::destroy_alloc_n(a, out_start, std::size_t(n_o - n_i));
1231 }
1232 }
1233
1234
1235
1236
1237
1238
1239
1240 template
1241 <typename Allocator
1242 ,typename I
1243 ,typename O
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);
1249 boost::container::uninitialized_move_alloc_n(a, inp_start, std::size_t(n_i - n_o), out_start);
1250 }
1251 else{
1252 out_start = boost::container::move_n(inp_start, n_i, out_start);
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
1282 ,typename O
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
1297 array_destructor_t new_values_destroyer(d_first, d_first, a);
1298
1299
1300
1301 O d_last = ::boost::container::uninitialized_move_alloc(a, first, pos, d_first);
1302 new_values_destroyer.set_end(d_last);
1303
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
1308
1309 (void) ::boost::container::uninitialized_move_alloc(a, pos, last, d_last);
1310
1311 new_values_destroyer.release();
1312 }
1313
1314
1315
1316
1317 template
1318 <typename Allocator
1319 ,typename F
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
1337 aux = first; ++aux;
1338 aux = boost::container::move(aux, pos, first);
1339
1340 insertion_proxy.copy_n_and_update(a, aux, 1u);
1341 on_exception.release();
1342 }
1343
1344 template
1345 <typename Allocator
1346 ,typename F
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
1364
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
1369 nxt = boost::container::move(nxt, pos, first);
1370
1371 insertion_proxy.copy_n_and_update(a, nxt, n);
1372 on_exception.release();
1373 }
1374 else {
1375
1376
1377 F aux = ::boost::container::uninitialized_move_alloc(a, first, pos, first - n);
1378 array_destructor_t on_exception(first -n, aux, a);
1379
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
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
1407 boost::container::move_backward(pos, last_m_n, last);
1408
1409 insertion_proxy.copy_n_and_update(a, pos, 1);
1410 on_exception.release();
1411 }
1412
1413 template
1414 <typename Allocator
1415 ,typename F
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
1433
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
1438 boost::container::move_backward(pos, last_m_n, last);
1439
1440 insertion_proxy.copy_n_and_update(a, pos, n);
1441 on_exception.release();
1442 }
1443 else {
1444
1445
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
1449 insertion_proxy.copy_n_and_update(a, pos, elems_after);
1450
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
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
1504 B old_finish = make_iterator_uadvance(old_start, old_size);
1505
1506
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
1512 if (raw_before >= before_plus_new) {
1513
1514
1515 array_destructor_t old_values_destroyer(old_start, a, old_size);
1516
1517
1518
1519
1520
1521
1522
1523
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
1530
1531 if (raw_before >= new_size) {
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 if (before_plus_new != new_size) {
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
1548 new_values_destroyer.release();
1549
1550
1551
1552 if(trivial_dctr_after_move)
1553 old_values_destroyer.release();
1554 }
1555
1556 else {
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569 BOOST_IF_CONSTEXPR(!trivial_dctr) {
1570
1571
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
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
1582 if(!trivial_dctr_after_move) {
1583 boost::container::destroy_alloc(a, remaining_pos, old_finish);
1584 }
1585 }
1586 else {
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
1595
1596 array_destructor_t old_values_destroyer(old_start, a, old_size);
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611 const bool do_after = n > raw_before;
1612
1613
1614
1615 if (raw_before <= elemsbefore) {
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633 ::boost::container::uninitialized_move_alloc_n(a, old_start, raw_before, new_start);
1634
1635
1636
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
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
1645 insertion_proxy.copy_n_and_update(a, next, new_1st_range);
1646
1647
1648 if (!do_after) {
1649
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
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
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
1685 old_values_destroyer.increment_size_backwards(raw_before);
1686
1687 if (do_after) {
1688
1689 insertion_proxy.copy_n_and_update(a, old_start, elemsbefore);
1690 }
1691 else {
1692
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
1699 B const move_end = ::boost::container::move_forward_overlapping(pos, old_finish, move_start);
1700 (void)move_end;
1701
1702
1703
1704 if(!trivial_dctr_after_move) {
1705 boost::container::destroy_alloc(a, move_end, old_finish);
1706 }
1707 }
1708 }
1709
1710
1711 if (do_after) {
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722 const size_type n_after = size_type(n - raw_before);
1723 const size_type elemsafter = size_type(old_size - elemsbefore);
1724
1725
1726 if (elemsafter >= n_after) {
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
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
1744 boost::container::move_backward_overlapping(pos, finish_n, old_finish);
1745
1746
1747 insertion_proxy.copy_n_and_update(a, pos, n_after);
1748 }
1749 else {
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759 const size_type mid_last_dist = size_type(n_after - elemsafter);
1760
1761
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
1768 insertion_proxy.copy_n_and_update(a, pos, elemsafter);
1769
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
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
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
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
1817 if (raw_after >= after_plus_new) {
1818
1819
1820 array_destructor_t old_values_destroyer(old_start, a, old_size);
1821
1822
1823
1824
1825
1826
1827
1828
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
1836
1837 if (raw_after >= new_size) {
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 ::boost::container::uninitialized_move_alloc(a, old_start, pos, new_start);
1850
1851 new_values_destroyer.release();
1852
1853
1854
1855 if(trivial_dctr_after_move)
1856 old_values_destroyer.release();
1857 }
1858
1859 else {
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
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
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
1888
1889 array_destructor_t old_values_destroyer(old_start, a, old_size);
1890
1891
1892
1893 if (raw_after > elemsafter) {
1894
1895
1896
1897
1898
1899
1900
1901
1902
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
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
1915 p = ::boost::container::move_backward_overlapping(old_start, pos, new_rng_start);
1916
1917
1918
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
1926
1927
1928
1929
1930
1931
1932
1933
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
1937 old_values_destroyer.increment_size_backwards(raw_after);
1938
1939
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
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 }
1975 }
1976
1977
1978 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
1979 #pragma GCC diagnostic pop
1980 #endif
1981
1982 #endif