xref: /freebsd-src/contrib/llvm-project/libcxx/include/__algorithm/move.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #ifndef _LIBCPP___ALGORITHM_MOVE_H
10fe6060f1SDimitry Andric #define _LIBCPP___ALGORITHM_MOVE_H
11fe6060f1SDimitry Andric 
12bdd1243dSDimitry Andric #include <__algorithm/copy_move_common.h>
1306c3fb27SDimitry Andric #include <__algorithm/for_each_segment.h>
1461cfbce3SDimitry Andric #include <__algorithm/iterator_operations.h>
15bdd1243dSDimitry Andric #include <__algorithm/min.h>
1604eeddc0SDimitry Andric #include <__config>
17bdd1243dSDimitry Andric #include <__iterator/segmented_iterator.h>
18bdd1243dSDimitry Andric #include <__type_traits/common_type.h>
19*0fca6ea1SDimitry Andric #include <__type_traits/is_constructible.h>
20fe6060f1SDimitry Andric #include <__utility/move.h>
2181ad6265SDimitry Andric #include <__utility/pair.h>
22fe6060f1SDimitry Andric 
23fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24fe6060f1SDimitry Andric #  pragma GCC system_header
25fe6060f1SDimitry Andric #endif
26fe6060f1SDimitry Andric 
27bdd1243dSDimitry Andric _LIBCPP_PUSH_MACROS
28bdd1243dSDimitry Andric #include <__undef_macros>
29bdd1243dSDimitry Andric 
30fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
31fe6060f1SDimitry Andric 
3261cfbce3SDimitry Andric template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
33bdd1243dSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
34bdd1243dSDimitry Andric __move(_InIter __first, _Sent __last, _OutIter __result);
35bdd1243dSDimitry Andric 
36bdd1243dSDimitry Andric template <class _AlgPolicy>
37*0fca6ea1SDimitry Andric struct __move_impl {
38bdd1243dSDimitry Andric   template <class _InIter, class _Sent, class _OutIter>
39bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
40bdd1243dSDimitry Andric   operator()(_InIter __first, _Sent __last, _OutIter __result) const {
4181ad6265SDimitry Andric     while (__first != __last) {
4261cfbce3SDimitry Andric       *__result = _IterOps<_AlgPolicy>::__iter_move(__first);
4381ad6265SDimitry Andric       ++__first;
4481ad6265SDimitry Andric       ++__result;
4581ad6265SDimitry Andric     }
4681ad6265SDimitry Andric     return std::make_pair(std::move(__first), std::move(__result));
47fe6060f1SDimitry Andric   }
48fe6060f1SDimitry Andric 
4906c3fb27SDimitry Andric   template <class _InIter, class _OutIter>
5006c3fb27SDimitry Andric   struct _MoveSegment {
5106c3fb27SDimitry Andric     using _Traits = __segmented_iterator_traits<_InIter>;
5206c3fb27SDimitry Andric 
5306c3fb27SDimitry Andric     _OutIter& __result_;
5406c3fb27SDimitry Andric 
555f757f3fSDimitry Andric     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit _MoveSegment(_OutIter& __result)
565f757f3fSDimitry Andric         : __result_(__result) {}
5706c3fb27SDimitry Andric 
585f757f3fSDimitry Andric     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
5906c3fb27SDimitry Andric     operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) {
6006c3fb27SDimitry Andric       __result_ = std::__move<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second;
6106c3fb27SDimitry Andric     }
6206c3fb27SDimitry Andric   };
6306c3fb27SDimitry Andric 
64bdd1243dSDimitry Andric   template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
65bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
66bdd1243dSDimitry Andric   operator()(_InIter __first, _InIter __last, _OutIter __result) const {
6706c3fb27SDimitry Andric     std::__for_each_segment(__first, __last, _MoveSegment<_InIter, _OutIter>(__result));
68bdd1243dSDimitry Andric     return std::make_pair(__last, std::move(__result));
69bdd1243dSDimitry Andric   }
7081ad6265SDimitry Andric 
71bdd1243dSDimitry Andric   template <class _InIter,
7281ad6265SDimitry Andric             class _OutIter,
7306c3fb27SDimitry Andric             __enable_if_t<__has_random_access_iterator_category<_InIter>::value &&
74bdd1243dSDimitry Andric                               !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,
75bdd1243dSDimitry Andric                           int> = 0>
76bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
7706c3fb27SDimitry Andric   operator()(_InIter __first, _InIter __last, _OutIter __result) const {
78bdd1243dSDimitry Andric     using _Traits = __segmented_iterator_traits<_OutIter>;
79bdd1243dSDimitry Andric     using _DiffT  = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric     if (__first == __last)
82bdd1243dSDimitry Andric       return std::make_pair(std::move(__first), std::move(__result));
83bdd1243dSDimitry Andric 
84bdd1243dSDimitry Andric     auto __local_first      = _Traits::__local(__result);
85bdd1243dSDimitry Andric     auto __segment_iterator = _Traits::__segment(__result);
86bdd1243dSDimitry Andric     while (true) {
87bdd1243dSDimitry Andric       auto __local_last = _Traits::__end(__segment_iterator);
88bdd1243dSDimitry Andric       auto __size       = std::min<_DiffT>(__local_last - __local_first, __last - __first);
89bdd1243dSDimitry Andric       auto __iters      = std::__move<_AlgPolicy>(__first, __first + __size, __local_first);
90bdd1243dSDimitry Andric       __first           = std::move(__iters.first);
91bdd1243dSDimitry Andric 
92bdd1243dSDimitry Andric       if (__first == __last)
93bdd1243dSDimitry Andric         return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second)));
94bdd1243dSDimitry Andric 
95bdd1243dSDimitry Andric       __local_first = _Traits::__begin(++__segment_iterator);
9681ad6265SDimitry Andric     }
97bdd1243dSDimitry Andric   }
98bdd1243dSDimitry Andric 
99bdd1243dSDimitry Andric   // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
100cb14a3feSDimitry Andric   template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
101bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
102bdd1243dSDimitry Andric   operator()(_In* __first, _In* __last, _Out* __result) const {
103bdd1243dSDimitry Andric     return std::__copy_trivial_impl(__first, __last, __result);
104bdd1243dSDimitry Andric   }
105bdd1243dSDimitry Andric };
10681ad6265SDimitry Andric 
10761cfbce3SDimitry Andric template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
108bdd1243dSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
10981ad6265SDimitry Andric __move(_InIter __first, _Sent __last, _OutIter __result) {
110*0fca6ea1SDimitry Andric   return std::__copy_move_unwrap_iters<__move_impl<_AlgPolicy> >(
111bdd1243dSDimitry Andric       std::move(__first), std::move(__last), std::move(__result));
112fe6060f1SDimitry Andric }
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric template <class _InputIterator, class _OutputIterator>
115bdd1243dSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
116bdd1243dSDimitry Andric move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
117bdd1243dSDimitry Andric   static_assert(is_copy_constructible<_InputIterator>::value, "Iterators has to be copy constructible.");
118bdd1243dSDimitry Andric   static_assert(is_copy_constructible<_OutputIterator>::value, "The output iterator has to be copy constructible.");
119bdd1243dSDimitry Andric 
120bdd1243dSDimitry Andric   return std::__move<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
121fe6060f1SDimitry Andric }
122fe6060f1SDimitry Andric 
123fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
124fe6060f1SDimitry Andric 
125bdd1243dSDimitry Andric _LIBCPP_POP_MACROS
126bdd1243dSDimitry Andric 
127fe6060f1SDimitry Andric #endif // _LIBCPP___ALGORITHM_MOVE_H
128