1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
10 #define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
12 #include <__cxx03/__algorithm/copy_move_common.h>
13 #include <__cxx03/__algorithm/iterator_operations.h>
14 #include <__cxx03/__algorithm/min.h>
15 #include <__cxx03/__config>
16 #include <__cxx03/__iterator/segmented_iterator.h>
17 #include <__cxx03/__type_traits/common_type.h>
18 #include <__cxx03/__type_traits/is_constructible.h>
19 #include <__cxx03/__utility/move.h>
20 #include <__cxx03/__utility/pair.h>
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 # pragma GCC system_header
27 #include <__cxx03/__undef_macros>
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 template <class _AlgPolicy
, class _BidirectionalIterator1
, class _Sentinel
, class _BidirectionalIterator2
>
32 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair
<_BidirectionalIterator1
, _BidirectionalIterator2
>
33 __move_backward(_BidirectionalIterator1 __first
, _Sentinel __last
, _BidirectionalIterator2 __result
);
35 template <class _AlgPolicy
>
36 struct __move_backward_impl
{
37 template <class _InIter
, class _Sent
, class _OutIter
>
38 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
39 operator()(_InIter __first
, _Sent __last
, _OutIter __result
) const {
40 auto __last_iter
= _IterOps
<_AlgPolicy
>::next(__first
, __last
);
41 auto __original_last_iter
= __last_iter
;
43 while (__first
!= __last_iter
) {
44 *--__result
= _IterOps
<_AlgPolicy
>::__iter_move(--__last_iter
);
47 return std::make_pair(std::move(__original_last_iter
), std::move(__result
));
50 template <class _InIter
, class _OutIter
, __enable_if_t
<__is_segmented_iterator
<_InIter
>::value
, int> = 0>
51 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
52 operator()(_InIter __first
, _InIter __last
, _OutIter __result
) const {
53 using _Traits
= __segmented_iterator_traits
<_InIter
>;
54 auto __sfirst
= _Traits::__segment(__first
);
55 auto __slast
= _Traits::__segment(__last
);
56 if (__sfirst
== __slast
) {
58 std::__move_backward
<_AlgPolicy
>(_Traits::__local(__first
), _Traits::__local(__last
), std::move(__result
));
59 return std::make_pair(__last
, __iters
.second
);
63 std::__move_backward
<_AlgPolicy
>(_Traits::__begin(__slast
), _Traits::__local(__last
), std::move(__result
))
66 while (__sfirst
!= __slast
) {
68 std::__move_backward
<_AlgPolicy
>(_Traits::__begin(__slast
), _Traits::__end(__slast
), std::move(__result
))
72 __result
= std::__move_backward
<_AlgPolicy
>(_Traits::__local(__first
), _Traits::__end(__slast
), std::move(__result
))
74 return std::make_pair(__last
, std::move(__result
));
77 template <class _InIter
,
79 __enable_if_t
<__has_random_access_iterator_category
<_InIter
>::value
&&
80 !__is_segmented_iterator
<_InIter
>::value
&& __is_segmented_iterator
<_OutIter
>::value
,
82 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
83 operator()(_InIter __first
, _InIter __last
, _OutIter __result
) const {
84 using _Traits
= __segmented_iterator_traits
<_OutIter
>;
85 using _DiffT
= typename common_type
<__iter_diff_t
<_InIter
>, __iter_diff_t
<_OutIter
> >::type
;
87 // When the range contains no elements, __result might not be a valid iterator
88 if (__first
== __last
)
89 return std::make_pair(__first
, __result
);
91 auto __orig_last
= __last
;
93 auto __local_last
= _Traits::__local(__result
);
94 auto __segment_iterator
= _Traits::__segment(__result
);
96 auto __local_first
= _Traits::__begin(__segment_iterator
);
97 auto __size
= std::min
<_DiffT
>(__local_last
- __local_first
, __last
- __first
);
98 auto __iter
= std::__move_backward
<_AlgPolicy
>(__last
- __size
, __last
, __local_last
).second
;
101 if (__first
== __last
)
102 return std::make_pair(std::move(__orig_last
), _Traits::__compose(__segment_iterator
, std::move(__iter
)));
104 __local_last
= _Traits::__end(--__segment_iterator
);
108 // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
109 template <class _In
, class _Out
, __enable_if_t
<__can_lower_move_assignment_to_memmove
<_In
, _Out
>::value
, int> = 0>
110 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_In
*, _Out
*>
111 operator()(_In
* __first
, _In
* __last
, _Out
* __result
) const {
112 return std::__copy_backward_trivial_impl(__first
, __last
, __result
);
116 template <class _AlgPolicy
, class _BidirectionalIterator1
, class _Sentinel
, class _BidirectionalIterator2
>
117 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair
<_BidirectionalIterator1
, _BidirectionalIterator2
>
118 __move_backward(_BidirectionalIterator1 __first
, _Sentinel __last
, _BidirectionalIterator2 __result
) {
119 static_assert(std::is_copy_constructible
<_BidirectionalIterator1
>::value
&&
120 std::is_copy_constructible
<_BidirectionalIterator1
>::value
,
121 "Iterators must be copy constructible.");
123 return std::__copy_move_unwrap_iters
<__move_backward_impl
<_AlgPolicy
> >(
124 std::move(__first
), std::move(__last
), std::move(__result
));
127 template <class _BidirectionalIterator1
, class _BidirectionalIterator2
>
128 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
129 move_backward(_BidirectionalIterator1 __first
, _BidirectionalIterator1 __last
, _BidirectionalIterator2 __result
) {
130 return std::__move_backward
<_ClassicAlgPolicy
>(std::move(__first
), std::move(__last
), std::move(__result
)).second
;
133 _LIBCPP_END_NAMESPACE_STD
137 #endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H