1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
10 #ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
11 #define BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
13 #ifndef BOOST_CONFIG_HPP
14 # include <boost/config.hpp>
17 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/container/allocator_traits.hpp>
24 #include <boost/container/detail/iterator.hpp>
25 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
26 #include <boost/container/detail/mpl.hpp>
27 #include <boost/container/detail/type_traits.hpp>
28 #include <boost/container/detail/construct_in_place.hpp>
31 #include <boost/move/adl_move_swap.hpp>
32 #include <boost/move/iterator.hpp>
33 #include <boost/move/utility_core.hpp>
35 #include <boost/core/no_exceptions_support.hpp>
37 #include <cstring> //for memmove/memcpy
39 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
40 #pragma GCC diagnostic push
41 //pair memcpy optimizations rightfully detected by GCC
42 # if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
43 # pragma GCC diagnostic ignored "-Wclass-memaccess"
45 //GCC 8 seems a bit confused about array access error with static_vector
46 //when out of bound exceptions are being thrown.
47 # if defined(BOOST_GCC) && (BOOST_GCC >= 80000) && (BOOST_GCC < 80200)
48 # pragma GCC diagnostic ignored "-Wstringop-overflow"
50 # pragma GCC diagnostic ignored "-Warray-bounds"
58 struct are_elements_contiguous
60 static const bool value = false;
63 /////////////////////////
65 /////////////////////////
68 struct are_elements_contiguous<T*>
70 static const bool value = true;
73 /////////////////////////
75 /////////////////////////
78 struct are_elements_contiguous< ::boost::move_iterator<It> >
79 : are_elements_contiguous<It>
84 /////////////////////////
86 /////////////////////////
88 template <class Pointer, bool IsConst>
91 } //namespace container {
93 namespace interprocess {
95 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
98 } //namespace interprocess {
100 namespace container {
104 /////////////////////////
105 //vector_[const_]iterator
106 /////////////////////////
108 template <class Pointer, bool IsConst>
109 struct are_elements_contiguous<boost::container::vec_iterator<Pointer, IsConst> >
111 static const bool value = true;
114 /////////////////////////
116 /////////////////////////
118 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
119 struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
121 static const bool value = true;
124 template <typename I, typename O>
125 struct are_contiguous_and_same
126 : boost::move_detail::and_
127 < are_elements_contiguous<I>
128 , are_elements_contiguous<O>
129 , is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
130 , typename ::boost::container::iterator_traits<O>::value_type
135 template <typename I, typename O>
136 struct is_memtransfer_copy_assignable
137 : boost::move_detail::and_
138 < are_contiguous_and_same<I, O>
139 , dtl::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >
143 template <typename I, typename O>
144 struct is_memtransfer_copy_constructible
145 : boost::move_detail::and_
146 < are_contiguous_and_same<I, O>
147 , dtl::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >
151 template <typename I, typename O, typename R>
152 struct enable_if_memtransfer_copy_constructible
153 : enable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
156 template <typename I, typename O, typename R>
157 struct disable_if_memtransfer_copy_constructible
158 : disable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
161 template <typename I, typename O, typename R>
162 struct enable_if_memtransfer_copy_assignable
163 : enable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
166 template <typename I, typename O, typename R>
167 struct disable_if_memtransfer_copy_assignable
168 : disable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
172 <typename I, // I models InputIterator
173 typename F> // F models ForwardIterator
174 inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
176 typedef typename boost::container::iterator_traits<I>::value_type value_type;
177 value_type *const dest_raw = boost::movelib::iterator_to_raw_pointer(r);
178 const value_type *const beg_raw = boost::movelib::iterator_to_raw_pointer(f);
179 const value_type *const end_raw = boost::movelib::iterator_to_raw_pointer(l);
180 if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
181 const typename boost::container::iterator_traits<I>::difference_type n = end_raw - beg_raw;
182 std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
183 boost::container::iterator_advance(r, n);
189 <typename I, // I models InputIterator
190 typename U, // U models unsigned integral constant
191 typename F> // F models ForwardIterator
192 F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
194 typedef typename boost::container::iterator_traits<I>::value_type value_type;
196 std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
197 boost::container::iterator_advance(r, n);
204 <typename I, // I models InputIterator
205 typename U, // U models unsigned integral constant
206 typename F> // F models ForwardIterator
207 I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
210 typedef typename boost::container::iterator_traits<I>::value_type value_type;
211 std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
212 boost::container::iterator_advance(f, n);
218 <typename I, // I models InputIterator
219 typename U, // U models unsigned integral constant
220 typename F> // F models ForwardIterator
221 I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
223 typedef typename boost::container::iterator_traits<I>::value_type value_type;
225 std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
226 boost::container::iterator_advance(f, n);
227 boost::container::iterator_advance(r, n);
232 template <typename O>
233 struct is_memzero_initializable
235 typedef typename ::boost::container::iterator_traits<O>::value_type value_type;
236 static const bool value = are_elements_contiguous<O>::value &&
237 ( dtl::is_integral<value_type>::value || dtl::is_enum<value_type>::value
238 #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
239 || dtl::is_pointer<value_type>::value
241 #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
242 || dtl::is_floating_point<value_type>::value
244 #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
245 || dtl::is_pod<value_type>::value
250 template <typename O, typename R>
251 struct enable_if_memzero_initializable
252 : enable_if_c<dtl::is_memzero_initializable<O>::value, R>
255 template <typename O, typename R>
256 struct disable_if_memzero_initializable
257 : enable_if_c<!dtl::is_memzero_initializable<O>::value, R>
260 template <typename I, typename R>
261 struct enable_if_trivially_destructible
262 : enable_if_c < dtl::is_trivially_destructible
263 <typename boost::container::iterator_traits<I>::value_type>::value
267 template <typename I, typename R>
268 struct disable_if_trivially_destructible
269 : enable_if_c <!dtl::is_trivially_destructible
270 <typename boost::container::iterator_traits<I>::value_type>::value
276 //////////////////////////////////////////////////////////////////////////////
278 // uninitialized_move_alloc
280 //////////////////////////////////////////////////////////////////////////////
285 //! for (; f != l; ++r, ++f)
286 //! allocator_traits::construct(a, &*r, boost::move(*f));
289 //! <b>Returns</b>: r
292 typename I, // I models InputIterator
293 typename F> // F models ForwardIterator
294 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
295 uninitialized_move_alloc(Allocator &a, I f, I l, F r)
300 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
305 for (; back != r; ++back){
306 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
316 typename I, // I models InputIterator
317 typename F> // F models ForwardIterator
318 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
319 uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
320 { return dtl::memmove(f, l, r); }
322 //////////////////////////////////////////////////////////////////////////////
324 // uninitialized_move_alloc_n
326 //////////////////////////////////////////////////////////////////////////////
330 //! for (; n--; ++r, ++f)
331 //! allocator_traits::construct(a, &*r, boost::move(*f));
334 //! <b>Returns</b>: r
337 typename I, // I models InputIterator
338 typename F> // F models ForwardIterator
339 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
340 uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
345 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
350 for (; back != r; ++back){
351 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
361 typename I, // I models InputIterator
362 typename F> // F models ForwardIterator
363 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
364 uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
365 { return dtl::memmove_n(f, n, r); }
367 //////////////////////////////////////////////////////////////////////////////
369 // uninitialized_move_alloc_n_source
371 //////////////////////////////////////////////////////////////////////////////
375 //! for (; n--; ++r, ++f)
376 //! allocator_traits::construct(a, &*r, boost::move(*f));
379 //! <b>Returns</b>: f (after incremented)
382 typename I, // I models InputIterator
383 typename F> // F models ForwardIterator
384 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
385 uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
390 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
395 for (; back != r; ++back){
396 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
406 typename I, // I models InputIterator
407 typename F> // F models ForwardIterator
408 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
409 uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
410 { return dtl::memmove_n_source(f, n, r); }
412 //////////////////////////////////////////////////////////////////////////////
414 // uninitialized_copy_alloc
416 //////////////////////////////////////////////////////////////////////////////
420 //! for (; f != l; ++r, ++f)
421 //! allocator_traits::construct(a, &*r, *f);
424 //! <b>Returns</b>: r
427 typename I, // I models InputIterator
428 typename F> // F models ForwardIterator
429 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
430 uninitialized_copy_alloc(Allocator &a, I f, I l, F r)
435 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
440 for (; back != r; ++back){
441 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
451 typename I, // I models InputIterator
452 typename F> // F models ForwardIterator
453 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
454 uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
455 { return dtl::memmove(f, l, r); }
457 //////////////////////////////////////////////////////////////////////////////
459 // uninitialized_copy_alloc_n
461 //////////////////////////////////////////////////////////////////////////////
465 //! for (; n--; ++r, ++f)
466 //! allocator_traits::construct(a, &*r, *f);
469 //! <b>Returns</b>: r
472 typename I, // I models InputIterator
473 typename F> // F models ForwardIterator
474 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
475 uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
480 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
485 for (; back != r; ++back){
486 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
496 typename I, // I models InputIterator
497 typename F> // F models ForwardIterator
498 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
499 uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
500 { return dtl::memmove_n(f, n, r); }
502 //////////////////////////////////////////////////////////////////////////////
504 // uninitialized_copy_alloc_n_source
506 //////////////////////////////////////////////////////////////////////////////
510 //! for (; n--; ++r, ++f)
511 //! allocator_traits::construct(a, &*r, *f);
514 //! <b>Returns</b>: f (after incremented)
517 typename I, // I models InputIterator
518 typename F> // F models ForwardIterator
519 inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
520 uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
525 boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
530 for (; back != r; ++back){
531 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
541 typename I, // I models InputIterator
542 typename F> // F models ForwardIterator
543 inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
544 uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
545 { return dtl::memmove_n_source(f, n, r); }
547 //////////////////////////////////////////////////////////////////////////////
549 // uninitialized_value_init_alloc_n
551 //////////////////////////////////////////////////////////////////////////////
555 //! for (; n--; ++r, ++f)
556 //! allocator_traits::construct(a, &*r);
559 //! <b>Returns</b>: r
562 typename F> // F models ForwardIterator
563 inline typename dtl::disable_if_memzero_initializable<F, F>::type
564 uninitialized_value_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
569 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r));
574 for (; back != r; ++back){
575 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
585 typename F> // F models ForwardIterator
586 inline typename dtl::enable_if_memzero_initializable<F, F>::type
587 uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
589 typedef typename boost::container::iterator_traits<F>::value_type value_type;
590 std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
591 boost::container::iterator_advance(r, n);
595 //////////////////////////////////////////////////////////////////////////////
597 // uninitialized_default_init_alloc_n
599 //////////////////////////////////////////////////////////////////////////////
603 //! for (; n--; ++r, ++f)
604 //! allocator_traits::construct(a, &*r);
607 //! <b>Returns</b>: r
610 typename F> // F models ForwardIterator
611 inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
616 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init);
621 for (; back != r; ++back){
622 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
630 //////////////////////////////////////////////////////////////////////////////
632 // uninitialized_fill_alloc
634 //////////////////////////////////////////////////////////////////////////////
638 //! for (; f != l; ++r, ++f)
639 //! allocator_traits::construct(a, &*r, *f);
642 //! <b>Returns</b>: r
645 typename F, // F models ForwardIterator
647 inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t)
652 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t);
657 for (; back != l; ++back){
658 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
666 //////////////////////////////////////////////////////////////////////////////
668 // uninitialized_fill_alloc_n
670 //////////////////////////////////////////////////////////////////////////////
674 //! for (; n--; ++r, ++f)
675 //! allocator_traits::construct(a, &*r, v);
678 //! <b>Returns</b>: r
682 typename F> // F models ForwardIterator
683 inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
688 allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v);
693 for (; back != r; ++back){
694 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
702 //////////////////////////////////////////////////////////////////////////////
706 //////////////////////////////////////////////////////////////////////////////
709 <typename I, // I models InputIterator
710 typename F> // F models ForwardIterator
711 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
722 <typename I, // I models InputIterator
723 typename F> // F models ForwardIterator
724 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
725 copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
726 { return dtl::memmove(f, l, r); }
728 //////////////////////////////////////////////////////////////////////////////
732 //////////////////////////////////////////////////////////////////////////////
735 <typename I, // I models InputIterator
736 typename U, // U models unsigned integral constant
737 typename F> // F models ForwardIterator
738 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
739 copy_n(I f, U n, F r)
750 <typename I, // I models InputIterator
751 typename U, // U models unsigned integral constant
752 typename F> // F models ForwardIterator
753 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
754 copy_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
755 { return dtl::memmove_n(f, n, r); }
757 //////////////////////////////////////////////////////////////////////////////
761 //////////////////////////////////////////////////////////////////////////////
764 <typename I, // I models InputIterator
765 typename U, // U models unsigned integral constant
766 typename F> // F models ForwardIterator
767 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
768 copy_n_source(I f, U n, F r)
771 boost::container::assign_in_place(r, f);
778 <typename I, // I models InputIterator
779 typename U, // U models unsigned integral constant
780 typename F> // F models ForwardIterator
781 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
782 copy_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
783 { return dtl::memmove_n_source(f, n, r); }
785 //////////////////////////////////////////////////////////////////////////////
787 // copy_n_source_dest
789 //////////////////////////////////////////////////////////////////////////////
792 <typename I, // I models InputIterator
793 typename U, // U models unsigned integral constant
794 typename F> // F models ForwardIterator
795 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
796 copy_n_source_dest(I f, U n, F &r)
806 <typename I, // I models InputIterator
807 typename U, // U models unsigned integral constant
808 typename F> // F models ForwardIterator
809 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
810 copy_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
811 { return dtl::memmove_n_source_dest(f, n, r); }
813 //////////////////////////////////////////////////////////////////////////////
817 //////////////////////////////////////////////////////////////////////////////
820 <typename I, // I models InputIterator
821 typename F> // F models ForwardIterator
822 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
826 *r = ::boost::move(*f);
833 <typename I, // I models InputIterator
834 typename F> // F models ForwardIterator
835 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
836 move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
837 { return dtl::memmove(f, l, r); }
839 //////////////////////////////////////////////////////////////////////////////
843 //////////////////////////////////////////////////////////////////////////////
846 <typename I, // I models InputIterator
847 typename U, // U models unsigned integral constant
848 typename F> // F models ForwardIterator
849 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
850 move_n(I f, U n, F r)
853 *r = ::boost::move(*f);
860 <typename I, // I models InputIterator
861 typename U, // U models unsigned integral constant
862 typename F> // F models ForwardIterator
863 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
864 move_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
865 { return dtl::memmove_n(f, n, r); }
868 //////////////////////////////////////////////////////////////////////////////
872 //////////////////////////////////////////////////////////////////////////////
875 <typename I, // I models BidirectionalIterator
876 typename F> // F models ForwardIterator
877 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
878 move_backward(I f, I l, F r)
882 *r = ::boost::move(*l);
888 <typename I, // I models InputIterator
889 typename F> // F models ForwardIterator
890 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
891 move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
893 typedef typename boost::container::iterator_traits<I>::value_type value_type;
894 const typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
896 std::memmove((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
900 //////////////////////////////////////////////////////////////////////////////
902 // move_n_source_dest
904 //////////////////////////////////////////////////////////////////////////////
907 <typename I // I models InputIterator
908 ,typename U // U models unsigned integral constant
909 ,typename F> // F models ForwardIterator
910 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
911 move_n_source_dest(I f, U n, F &r)
914 *r = ::boost::move(*f);
921 <typename I // I models InputIterator
922 ,typename U // U models unsigned integral constant
923 ,typename F> // F models ForwardIterator
924 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
925 move_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
926 { return dtl::memmove_n_source_dest(f, n, r); }
928 //////////////////////////////////////////////////////////////////////////////
932 //////////////////////////////////////////////////////////////////////////////
935 <typename I // I models InputIterator
936 ,typename U // U models unsigned integral constant
937 ,typename F> // F models ForwardIterator
938 inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
939 move_n_source(I f, U n, F r)
942 *r = ::boost::move(*f);
949 <typename I // I models InputIterator
950 ,typename U // U models unsigned integral constant
951 ,typename F> // F models ForwardIterator
952 inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
953 move_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
954 { return dtl::memmove_n_source(f, n, r); }
956 //////////////////////////////////////////////////////////////////////////////
960 //////////////////////////////////////////////////////////////////////////////
964 ,typename I // I models InputIterator
965 ,typename U> // U models unsigned integral constant
966 inline typename dtl::disable_if_trivially_destructible<I, void>::type
967 destroy_alloc_n(Allocator &a, I f, U n)
971 allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
978 ,typename I // I models InputIterator
979 ,typename U> // U models unsigned integral constant
980 inline typename dtl::enable_if_trivially_destructible<I, void>::type
981 destroy_alloc_n(Allocator &, I, U)
984 //////////////////////////////////////////////////////////////////////////////
988 //////////////////////////////////////////////////////////////////////////////
991 <std::size_t MaxTmpBytes
993 ,typename F // F models ForwardIterator
994 ,typename G // G models ForwardIterator
996 inline typename dtl::disable_if_memtransfer_copy_assignable<F, G, void>::type
997 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
998 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
1000 typename allocator_traits<Allocator>::size_type n = 0;
1001 for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
1002 boost::adl_move_swap(*short_range_f, *large_range_f);
1004 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
1005 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
1008 static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
1011 <std::size_t MaxTmpBytes
1013 ,typename F // F models ForwardIterator
1014 ,typename G // G models ForwardIterator
1016 inline typename dtl::enable_if_c
1017 < dtl::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
1019 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
1020 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
1022 typedef typename allocator_traits<Allocator>::value_type value_type;
1023 typedef typename dtl::aligned_storage
1024 <MaxTmpBytes, dtl::alignment_of<value_type>::value>::type storage_type;
1025 storage_type storage;
1027 const std::size_t n_i_bytes = sizeof(value_type)*n_i;
1028 void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f));
1029 void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f));
1030 void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage.data));
1031 std::memcpy(stora_ptr, large_ptr, n_i_bytes);
1032 std::memcpy(large_ptr, short_ptr, n_i_bytes);
1033 std::memcpy(short_ptr, stora_ptr, n_i_bytes);
1034 boost::container::iterator_advance(large_range_f, n_i);
1035 boost::container::iterator_advance(short_range_f, n_i);
1036 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
1037 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
1041 <std::size_t MaxTmpBytes
1043 ,typename F // F models ForwardIterator
1044 ,typename G // G models ForwardIterator
1046 inline typename dtl::enable_if_c
1047 < dtl::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
1049 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
1050 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
1052 typedef typename allocator_traits<Allocator>::value_type value_type;
1053 typedef typename dtl::aligned_storage
1054 <DeepSwapAllocNMaxStorage, dtl::alignment_of<value_type>::value>::type storage_type;
1055 storage_type storage;
1056 const std::size_t sizeof_storage = sizeof(storage);
1058 std::size_t n_i_bytes = sizeof(value_type)*n_i;
1059 char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)));
1060 char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)));
1061 char *stora_ptr = static_cast<char*>(static_cast<void*>(storage.data));
1063 std::size_t szt_times = n_i_bytes/sizeof_storage;
1064 const std::size_t szt_rem = n_i_bytes%sizeof_storage;
1066 //Loop unrolling using Duff's device, as it seems it helps on some architectures
1067 const std::size_t Unroll = 4;
1068 std::size_t n = (szt_times + (Unroll-1))/Unroll;
1069 const std::size_t branch_number = (!szt_times)*Unroll + (szt_times % Unroll);
1070 switch(branch_number){
1074 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1075 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1076 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1077 large_ptr += sizeof_storage;
1078 short_ptr += sizeof_storage;
1081 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1082 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1083 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1084 large_ptr += sizeof_storage;
1085 short_ptr += sizeof_storage;
1088 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1089 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1090 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1091 large_ptr += sizeof_storage;
1092 short_ptr += sizeof_storage;
1095 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1096 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1097 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1098 large_ptr += sizeof_storage;
1099 short_ptr += sizeof_storage;
1102 std::memcpy(stora_ptr, large_ptr, szt_rem);
1103 std::memcpy(large_ptr, short_ptr, szt_rem);
1104 std::memcpy(short_ptr, stora_ptr, szt_rem);
1105 boost::container::iterator_advance(large_range_f, n_i);
1106 boost::container::iterator_advance(short_range_f, n_i);
1107 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
1108 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
1112 //////////////////////////////////////////////////////////////////////////////
1114 // copy_assign_range_alloc_n
1116 //////////////////////////////////////////////////////////////////////////////
1120 ,typename I // F models InputIterator
1121 ,typename O // G models OutputIterator
1123 void copy_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
1124 , O out_start, typename allocator_traits<Allocator>::size_type n_o )
1127 inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw
1128 boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
1131 out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
1132 boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
1136 //////////////////////////////////////////////////////////////////////////////
1138 // move_assign_range_alloc_n
1140 //////////////////////////////////////////////////////////////////////////////
1144 ,typename I // F models InputIterator
1145 ,typename O // G models OutputIterator
1147 void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
1148 , O out_start, typename allocator_traits<Allocator>::size_type n_o )
1151 inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw
1152 boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
1155 out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
1156 boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
1160 } //namespace container {
1161 } //namespace boost {
1163 //#pragma GCC diagnostic ignored "-Wclass-memaccess"
1164 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600)
1165 #pragma GCC diagnostic pop
1168 #endif //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP