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/container/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 emmove/memcpy
41 namespace container_detail {
44 struct are_elements_contiguous
46 static const bool value = false;
49 /////////////////////////
51 /////////////////////////
54 struct are_elements_contiguous<T*>
56 static const bool value = true;
59 /////////////////////////
61 /////////////////////////
64 struct are_elements_contiguous< ::boost::move_iterator<It> >
65 : are_elements_contiguous<It>
68 /////////////////////////
70 /////////////////////////
72 #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
74 template<class Pointer>
75 class vector_iterator;
77 template<class Pointer>
78 class vector_const_iterator;
80 #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
82 } //namespace container_detail {
83 } //namespace container {
85 namespace interprocess {
87 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
90 } //namespace interprocess {
94 namespace container_detail {
96 /////////////////////////
97 //vector_[const_]iterator
98 /////////////////////////
100 #ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
102 template<class Pointer>
103 struct are_elements_contiguous<boost::container::container_detail::vector_iterator<Pointer> >
105 static const bool value = true;
108 template<class Pointer>
109 struct are_elements_contiguous<boost::container::container_detail::vector_const_iterator<Pointer> >
111 static const bool value = true;
114 #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
116 /////////////////////////
118 /////////////////////////
120 template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
121 struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
123 static const bool value = true;
126 template <typename I, typename O>
127 struct are_contiguous_and_same
128 : boost::move_detail::and_
129 < are_elements_contiguous<I>
130 , are_elements_contiguous<O>
131 , is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
132 , typename ::boost::container::iterator_traits<O>::value_type
137 template <typename I, typename O>
138 struct is_memtransfer_copy_assignable
139 : boost::move_detail::and_
140 < are_contiguous_and_same<I, O>
141 , container_detail::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >
145 template <typename I, typename O>
146 struct is_memtransfer_copy_constructible
147 : boost::move_detail::and_
148 < are_contiguous_and_same<I, O>
149 , container_detail::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >
153 template <typename I, typename O, typename R>
154 struct enable_if_memtransfer_copy_constructible
155 : enable_if<container_detail::is_memtransfer_copy_constructible<I, O>, R>
158 template <typename I, typename O, typename R>
159 struct disable_if_memtransfer_copy_constructible
160 : disable_if<container_detail::is_memtransfer_copy_constructible<I, O>, R>
163 template <typename I, typename O, typename R>
164 struct enable_if_memtransfer_copy_assignable
165 : enable_if<container_detail::is_memtransfer_copy_assignable<I, O>, R>
168 template <typename I, typename O, typename R>
169 struct disable_if_memtransfer_copy_assignable
170 : disable_if<container_detail::is_memtransfer_copy_assignable<I, O>, R>
174 <typename I, // I models InputIterator
175 typename F> // F models ForwardIterator
176 inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
178 typedef typename boost::container::iterator_traits<I>::value_type value_type;
179 typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
181 std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
182 boost::container::iterator_advance(r, n);
188 <typename I, // I models InputIterator
189 typename F> // F models ForwardIterator
190 F memmove_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
192 typedef typename boost::container::iterator_traits<I>::value_type value_type;
194 std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
195 boost::container::iterator_advance(r, n);
201 <typename I, // I models InputIterator
202 typename F> // F models ForwardIterator
203 I memmove_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
206 typedef typename boost::container::iterator_traits<I>::value_type value_type;
207 std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
208 boost::container::iterator_advance(f, n);
214 <typename I, // I models InputIterator
215 typename F> // F models ForwardIterator
216 I memmove_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
218 typedef typename boost::container::iterator_traits<I>::value_type value_type;
220 std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
221 boost::container::iterator_advance(f, n);
222 boost::container::iterator_advance(r, n);
227 template <typename O>
228 struct is_memzero_initializable
230 typedef typename ::boost::container::iterator_traits<O>::value_type value_type;
231 static const bool value = are_elements_contiguous<O>::value &&
232 ( container_detail::is_integral<value_type>::value || container_detail::is_enum<value_type>::value
233 #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
234 || container_detail::is_pointer<value_type>::value
236 #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
237 || container_detail::is_floating_point<value_type>::value
239 #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
240 || container_detail::is_pod<value_type>::value
245 template <typename O, typename R>
246 struct enable_if_memzero_initializable
247 : enable_if_c<container_detail::is_memzero_initializable<O>::value, R>
250 template <typename O, typename R>
251 struct disable_if_memzero_initializable
252 : enable_if_c<!container_detail::is_memzero_initializable<O>::value, R>
255 template <typename I, typename R>
256 struct enable_if_trivially_destructible
257 : enable_if_c < container_detail::is_trivially_destructible
258 <typename boost::container::iterator_traits<I>::value_type>::value
262 template <typename I, typename R>
263 struct disable_if_trivially_destructible
264 : enable_if_c <!container_detail::is_trivially_destructible
265 <typename boost::container::iterator_traits<I>::value_type>::value
269 } //namespace container_detail {
271 //////////////////////////////////////////////////////////////////////////////
273 // uninitialized_move_alloc
275 //////////////////////////////////////////////////////////////////////////////
280 //! for (; f != l; ++r, ++f)
281 //! allocator_traits::construct(a, &*r, boost::move(*f));
284 //! <b>Returns</b>: r
287 typename I, // I models InputIterator
288 typename F> // F models ForwardIterator
289 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
290 uninitialized_move_alloc(Allocator &a, I f, I l, F r)
295 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
300 for (; back != r; ++back){
301 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
311 typename I, // I models InputIterator
312 typename F> // F models ForwardIterator
313 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
314 uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
315 { return container_detail::memmove(f, l, r); }
317 //////////////////////////////////////////////////////////////////////////////
319 // uninitialized_move_alloc_n
321 //////////////////////////////////////////////////////////////////////////////
325 //! for (; n--; ++r, ++f)
326 //! allocator_traits::construct(a, &*r, boost::move(*f));
329 //! <b>Returns</b>: r
332 typename I, // I models InputIterator
333 typename F> // F models ForwardIterator
334 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
335 uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
340 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
345 for (; back != r; ++back){
346 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
356 typename I, // I models InputIterator
357 typename F> // F models ForwardIterator
358 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
359 uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
360 { return container_detail::memmove_n(f, n, r); }
362 //////////////////////////////////////////////////////////////////////////////
364 // uninitialized_move_alloc_n_source
366 //////////////////////////////////////////////////////////////////////////////
370 //! for (; n--; ++r, ++f)
371 //! allocator_traits::construct(a, &*r, boost::move(*f));
374 //! <b>Returns</b>: f (after incremented)
377 typename I, // I models InputIterator
378 typename F> // F models ForwardIterator
379 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
380 uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
385 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
390 for (; back != r; ++back){
391 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
401 typename I, // I models InputIterator
402 typename F> // F models ForwardIterator
403 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
404 uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
405 { return container_detail::memmove_n_source(f, n, r); }
407 //////////////////////////////////////////////////////////////////////////////
409 // uninitialized_copy_alloc
411 //////////////////////////////////////////////////////////////////////////////
415 //! for (; f != l; ++r, ++f)
416 //! allocator_traits::construct(a, &*r, *f);
419 //! <b>Returns</b>: r
422 typename I, // I models InputIterator
423 typename F> // F models ForwardIterator
424 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
425 uninitialized_copy_alloc(Allocator &a, I f, I l, F r)
430 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
435 for (; back != r; ++back){
436 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
446 typename I, // I models InputIterator
447 typename F> // F models ForwardIterator
448 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
449 uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
450 { return container_detail::memmove(f, l, r); }
452 //////////////////////////////////////////////////////////////////////////////
454 // uninitialized_copy_alloc_n
456 //////////////////////////////////////////////////////////////////////////////
460 //! for (; n--; ++r, ++f)
461 //! allocator_traits::construct(a, &*r, *f);
464 //! <b>Returns</b>: r
467 typename I, // I models InputIterator
468 typename F> // F models ForwardIterator
469 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
470 uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
475 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
480 for (; back != r; ++back){
481 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
491 typename I, // I models InputIterator
492 typename F> // F models ForwardIterator
493 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
494 uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
495 { return container_detail::memmove_n(f, n, r); }
497 //////////////////////////////////////////////////////////////////////////////
499 // uninitialized_copy_alloc_n_source
501 //////////////////////////////////////////////////////////////////////////////
505 //! for (; n--; ++r, ++f)
506 //! allocator_traits::construct(a, &*r, *f);
509 //! <b>Returns</b>: f (after incremented)
512 typename I, // I models InputIterator
513 typename F> // F models ForwardIterator
514 inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
515 uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
520 boost::container::construct_in_place(a, container_detail::iterator_to_raw_pointer(r), f);
525 for (; back != r; ++back){
526 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
536 typename I, // I models InputIterator
537 typename F> // F models ForwardIterator
538 inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
539 uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
540 { return container_detail::memmove_n_source(f, n, r); }
542 //////////////////////////////////////////////////////////////////////////////
544 // uninitialized_value_init_alloc_n
546 //////////////////////////////////////////////////////////////////////////////
550 //! for (; n--; ++r, ++f)
551 //! allocator_traits::construct(a, &*r);
554 //! <b>Returns</b>: r
557 typename F> // F models ForwardIterator
558 inline typename container_detail::disable_if_memzero_initializable<F, F>::type
559 uninitialized_value_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r)
564 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r));
569 for (; back != r; ++back){
570 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
580 typename F> // F models ForwardIterator
581 inline typename container_detail::enable_if_memzero_initializable<F, F>::type
582 uninitialized_value_init_alloc_n(Allocator &, typename allocator_traits<Allocator>::difference_type n, F r)
584 typedef typename boost::container::iterator_traits<F>::value_type value_type;
585 std::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
586 boost::container::iterator_advance(r, n);
590 //////////////////////////////////////////////////////////////////////////////
592 // uninitialized_default_init_alloc_n
594 //////////////////////////////////////////////////////////////////////////////
598 //! for (; n--; ++r, ++f)
599 //! allocator_traits::construct(a, &*r);
602 //! <b>Returns</b>: r
605 typename F> // F models ForwardIterator
606 inline F uninitialized_default_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r)
611 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init);
616 for (; back != r; ++back){
617 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
625 //////////////////////////////////////////////////////////////////////////////
627 // uninitialized_fill_alloc
629 //////////////////////////////////////////////////////////////////////////////
633 //! for (; f != l; ++r, ++f)
634 //! allocator_traits::construct(a, &*r, *f);
637 //! <b>Returns</b>: r
640 typename F, // F models ForwardIterator
642 inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t)
647 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(f), t);
652 for (; back != l; ++back){
653 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
661 //////////////////////////////////////////////////////////////////////////////
663 // uninitialized_fill_alloc_n
665 //////////////////////////////////////////////////////////////////////////////
669 //! for (; n--; ++r, ++f)
670 //! allocator_traits::construct(a, &*r, v);
673 //! <b>Returns</b>: r
677 typename F> // F models ForwardIterator
678 inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename allocator_traits<Allocator>::difference_type n, F r)
683 allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), v);
688 for (; back != r; ++back){
689 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back));
697 //////////////////////////////////////////////////////////////////////////////
701 //////////////////////////////////////////////////////////////////////////////
704 <typename I, // I models InputIterator
705 typename F> // F models ForwardIterator
706 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
717 <typename I, // I models InputIterator
718 typename F> // F models ForwardIterator
719 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
720 copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
721 { return container_detail::memmove(f, l, r); }
723 //////////////////////////////////////////////////////////////////////////////
727 //////////////////////////////////////////////////////////////////////////////
730 <typename I, // I models InputIterator
731 typename F> // F models ForwardIterator
732 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
733 copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
743 <typename I, // I models InputIterator
744 typename F> // F models ForwardIterator
745 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
746 copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
747 { return container_detail::memmove_n(f, n, r); }
749 //////////////////////////////////////////////////////////////////////////////
753 //////////////////////////////////////////////////////////////////////////////
756 <typename I, // I models InputIterator
757 typename F> // F models ForwardIterator
758 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
759 copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
762 boost::container::assign_in_place(r, f);
769 <typename I, // I models InputIterator
770 typename F> // F models ForwardIterator
771 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
772 copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
773 { return container_detail::memmove_n_source(f, n, r); }
775 //////////////////////////////////////////////////////////////////////////////
777 // copy_n_source_dest
779 //////////////////////////////////////////////////////////////////////////////
782 <typename I, // I models InputIterator
783 typename F> // F models ForwardIterator
784 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
785 copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r)
795 <typename I, // I models InputIterator
796 typename F> // F models ForwardIterator
797 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
798 copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
799 { return container_detail::memmove_n_source_dest(f, n, r); }
801 //////////////////////////////////////////////////////////////////////////////
805 //////////////////////////////////////////////////////////////////////////////
808 <typename I, // I models InputIterator
809 typename F> // F models ForwardIterator
810 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
814 *r = ::boost::move(*f);
821 <typename I, // I models InputIterator
822 typename F> // F models ForwardIterator
823 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
824 move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
825 { return container_detail::memmove(f, l, r); }
827 //////////////////////////////////////////////////////////////////////////////
831 //////////////////////////////////////////////////////////////////////////////
834 <typename I, // I models InputIterator
835 typename F> // F models ForwardIterator
836 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
837 move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
840 *r = ::boost::move(*f);
847 <typename I, // I models InputIterator
848 typename F> // F models ForwardIterator
849 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
850 move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
851 { return container_detail::memmove_n(f, n, r); }
854 //////////////////////////////////////////////////////////////////////////////
858 //////////////////////////////////////////////////////////////////////////////
861 <typename I, // I models BidirectionalIterator
862 typename F> // F models ForwardIterator
863 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
864 move_backward(I f, I l, F r)
868 *r = ::boost::move(*l);
874 <typename I, // I models InputIterator
875 typename F> // F models ForwardIterator
876 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
877 move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
879 typedef typename boost::container::iterator_traits<I>::value_type value_type;
880 const typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
882 std::memmove((container_detail::iterator_to_raw_pointer)(r), (container_detail::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
886 //////////////////////////////////////////////////////////////////////////////
888 // move_n_source_dest
890 //////////////////////////////////////////////////////////////////////////////
893 <typename I // I models InputIterator
894 ,typename F> // F models ForwardIterator
895 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
896 move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r)
899 *r = ::boost::move(*f);
906 <typename I // I models InputIterator
907 ,typename F> // F models ForwardIterator
908 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
909 move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
910 { return container_detail::memmove_n_source_dest(f, n, r); }
912 //////////////////////////////////////////////////////////////////////////////
916 //////////////////////////////////////////////////////////////////////////////
919 <typename I // I models InputIterator
920 ,typename F> // F models ForwardIterator
921 inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
922 move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r)
925 *r = ::boost::move(*f);
932 <typename I // I models InputIterator
933 ,typename F> // F models ForwardIterator
934 inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
935 move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
936 { return container_detail::memmove_n_source(f, n, r); }
938 //////////////////////////////////////////////////////////////////////////////
942 //////////////////////////////////////////////////////////////////////////////
946 ,typename I // I models InputIterator
947 ,typename U> // U models unsigned integral constant
948 inline typename container_detail::disable_if_trivially_destructible<I, void>::type
949 destroy_alloc_n(Allocator &a, I f, U n)
952 allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(f));
959 ,typename I // I models InputIterator
960 ,typename U> // U models unsigned integral constant
961 inline typename container_detail::enable_if_trivially_destructible<I, void>::type
962 destroy_alloc_n(Allocator &, I, U)
965 //////////////////////////////////////////////////////////////////////////////
969 //////////////////////////////////////////////////////////////////////////////
972 <std::size_t MaxTmpBytes
974 ,typename F // F models ForwardIterator
975 ,typename G // G models ForwardIterator
977 inline typename container_detail::disable_if_memtransfer_copy_assignable<F, G, void>::type
978 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
979 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
981 typename allocator_traits<Allocator>::size_type n = 0;
982 for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
983 boost::adl_move_swap(*short_range_f, *large_range_f);
985 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
986 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
989 static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
992 <std::size_t MaxTmpBytes
994 ,typename F // F models ForwardIterator
995 ,typename G // G models ForwardIterator
997 inline typename container_detail::enable_if_c
998 < container_detail::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
1000 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
1001 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
1003 typedef typename allocator_traits<Allocator>::value_type value_type;
1004 typedef typename container_detail::aligned_storage
1005 <MaxTmpBytes, container_detail::alignment_of<value_type>::value>::type storage_type;
1006 storage_type storage;
1008 const std::size_t n_i_bytes = sizeof(value_type)*n_i;
1009 void *const large_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f));
1010 void *const short_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f));
1011 void *const stora_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(storage));
1012 std::memcpy(stora_ptr, large_ptr, n_i_bytes);
1013 std::memcpy(large_ptr, short_ptr, n_i_bytes);
1014 std::memcpy(short_ptr, stora_ptr, n_i_bytes);
1015 boost::container::iterator_advance(large_range_f, n_i);
1016 boost::container::iterator_advance(short_range_f, n_i);
1017 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
1018 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
1022 <std::size_t MaxTmpBytes
1024 ,typename F // F models ForwardIterator
1025 ,typename G // G models ForwardIterator
1027 inline typename container_detail::enable_if_c
1028 < container_detail::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
1030 deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i
1031 , G large_range_f, typename allocator_traits<Allocator>::size_type n_j)
1033 typedef typename allocator_traits<Allocator>::value_type value_type;
1034 typedef typename container_detail::aligned_storage
1035 <DeepSwapAllocNMaxStorage, container_detail::alignment_of<value_type>::value>::type storage_type;
1036 storage_type storage;
1037 const std::size_t sizeof_storage = sizeof(storage);
1039 std::size_t n_i_bytes = sizeof(value_type)*n_i;
1040 char *large_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f)));
1041 char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f)));
1042 char *stora_ptr = static_cast<char*>(static_cast<void*>(&storage));
1044 std::size_t szt_times = n_i_bytes/sizeof_storage;
1045 const std::size_t szt_rem = n_i_bytes%sizeof_storage;
1047 //Loop unrolling using Duff's device, as it seems it helps on some architectures
1048 const std::size_t Unroll = 4;
1049 std::size_t n = (szt_times + (Unroll-1))/Unroll;
1050 const std::size_t branch_number = (!szt_times)*Unroll + (szt_times % Unroll);
1051 switch(branch_number){
1055 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1056 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1057 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1058 large_ptr += sizeof_storage;
1059 short_ptr += sizeof_storage;
1060 BOOST_CONTAINER_FALLTHOUGH
1062 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1063 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1064 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1065 large_ptr += sizeof_storage;
1066 short_ptr += sizeof_storage;
1067 BOOST_CONTAINER_FALLTHOUGH
1069 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1070 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1071 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1072 large_ptr += sizeof_storage;
1073 short_ptr += sizeof_storage;
1074 BOOST_CONTAINER_FALLTHOUGH
1076 std::memcpy(stora_ptr, large_ptr, sizeof_storage);
1077 std::memcpy(large_ptr, short_ptr, sizeof_storage);
1078 std::memcpy(short_ptr, stora_ptr, sizeof_storage);
1079 large_ptr += sizeof_storage;
1080 short_ptr += sizeof_storage;
1083 std::memcpy(stora_ptr, large_ptr, szt_rem);
1084 std::memcpy(large_ptr, short_ptr, szt_rem);
1085 std::memcpy(short_ptr, stora_ptr, szt_rem);
1086 boost::container::iterator_advance(large_range_f, n_i);
1087 boost::container::iterator_advance(short_range_f, n_i);
1088 boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
1089 boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
1093 //////////////////////////////////////////////////////////////////////////////
1095 // copy_assign_range_alloc_n
1097 //////////////////////////////////////////////////////////////////////////////
1101 ,typename I // F models InputIterator
1102 ,typename O // G models OutputIterator
1104 void copy_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
1105 , O out_start, typename allocator_traits<Allocator>::size_type n_o )
1108 inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw
1109 boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
1112 out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
1113 boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
1117 //////////////////////////////////////////////////////////////////////////////
1119 // move_assign_range_alloc_n
1121 //////////////////////////////////////////////////////////////////////////////
1125 ,typename I // F models InputIterator
1126 ,typename O // G models OutputIterator
1128 void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i
1129 , O out_start, typename allocator_traits<Allocator>::size_type n_o )
1132 inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw
1133 boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
1136 out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
1137 boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
1141 } //namespace container {
1142 } //namespace boost {
1144 #endif //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP