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_COPY_BACKWARD_H
10 #define _LIBCPP___ALGORITHM_COPY_BACKWARD_H
12 #include <__algorithm/copy_move_common.h>
13 #include <__algorithm/iterator_operations.h>
14 #include <__algorithm/min.h>
16 #include <__iterator/iterator_traits.h>
17 #include <__iterator/segmented_iterator.h>
18 #include <__type_traits/common_type.h>
19 #include <__type_traits/enable_if.h>
20 #include <__type_traits/is_constructible.h>
21 #include <__utility/move.h>
22 #include <__utility/pair.h>
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
29 #include <__undef_macros>
31 _LIBCPP_BEGIN_NAMESPACE_STD
33 template <class _AlgPolicy
, class _InIter
, class _Sent
, class _OutIter
>
34 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair
<_InIter
, _OutIter
>
35 __copy_backward(_InIter __first
, _Sent __last
, _OutIter __result
);
37 template <class _AlgPolicy
>
38 struct __copy_backward_impl
{
39 template <class _InIter
, class _Sent
, class _OutIter
>
40 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
41 operator()(_InIter __first
, _Sent __last
, _OutIter __result
) const {
42 auto __last_iter
= _IterOps
<_AlgPolicy
>::next(__first
, __last
);
43 auto __original_last_iter
= __last_iter
;
45 while (__first
!= __last_iter
) {
46 *--__result
= *--__last_iter
;
49 return std::make_pair(std::move(__original_last_iter
), std::move(__result
));
52 template <class _InIter
, class _OutIter
, __enable_if_t
<__is_segmented_iterator
<_InIter
>::value
, int> = 0>
53 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
54 operator()(_InIter __first
, _InIter __last
, _OutIter __result
) const {
55 using _Traits
= __segmented_iterator_traits
<_InIter
>;
56 auto __sfirst
= _Traits::__segment(__first
);
57 auto __slast
= _Traits::__segment(__last
);
58 if (__sfirst
== __slast
) {
60 std::__copy_backward
<_AlgPolicy
>(_Traits::__local(__first
), _Traits::__local(__last
), std::move(__result
));
61 return std::make_pair(__last
, __iters
.second
);
65 std::__copy_backward
<_AlgPolicy
>(_Traits::__begin(__slast
), _Traits::__local(__last
), std::move(__result
))
68 while (__sfirst
!= __slast
) {
70 std::__copy_backward
<_AlgPolicy
>(_Traits::__begin(__slast
), _Traits::__end(__slast
), std::move(__result
))
74 __result
= std::__copy_backward
<_AlgPolicy
>(_Traits::__local(__first
), _Traits::__end(__slast
), std::move(__result
))
76 return std::make_pair(__last
, std::move(__result
));
79 template <class _InIter
,
81 __enable_if_t
<__has_random_access_iterator_category
<_InIter
>::value
&&
82 !__is_segmented_iterator
<_InIter
>::value
&& __is_segmented_iterator
<_OutIter
>::value
,
84 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_InIter
, _OutIter
>
85 operator()(_InIter __first
, _InIter __last
, _OutIter __result
) const {
86 using _Traits
= __segmented_iterator_traits
<_OutIter
>;
87 auto __orig_last
= __last
;
88 auto __segment_iterator
= _Traits::__segment(__result
);
90 // When the range contains no elements, __result might not be a valid iterator
91 if (__first
== __last
)
92 return std::make_pair(__first
, __result
);
94 auto __local_last
= _Traits::__local(__result
);
96 using _DiffT
= typename common_type
<__iter_diff_t
<_InIter
>, __iter_diff_t
<_OutIter
> >::type
;
98 auto __local_first
= _Traits::__begin(__segment_iterator
);
99 auto __size
= std::min
<_DiffT
>(__local_last
- __local_first
, __last
- __first
);
100 auto __iter
= std::__copy_backward
<_AlgPolicy
>(__last
- __size
, __last
, __local_last
).second
;
103 if (__first
== __last
)
104 return std::make_pair(std::move(__orig_last
), _Traits::__compose(__segment_iterator
, std::move(__iter
)));
105 --__segment_iterator
;
106 __local_last
= _Traits::__end(__segment_iterator
);
110 // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
111 template <class _In
, class _Out
, __enable_if_t
<__can_lower_copy_assignment_to_memmove
<_In
, _Out
>::value
, int> = 0>
112 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair
<_In
*, _Out
*>
113 operator()(_In
* __first
, _In
* __last
, _Out
* __result
) const {
114 return std::__copy_backward_trivial_impl(__first
, __last
, __result
);
118 template <class _AlgPolicy
, class _BidirectionalIterator1
, class _Sentinel
, class _BidirectionalIterator2
>
119 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair
<_BidirectionalIterator1
, _BidirectionalIterator2
>
120 __copy_backward(_BidirectionalIterator1 __first
, _Sentinel __last
, _BidirectionalIterator2 __result
) {
121 return std::__copy_move_unwrap_iters
<__copy_backward_impl
<_AlgPolicy
> >(
122 std::move(__first
), std::move(__last
), std::move(__result
));
125 template <class _BidirectionalIterator1
, class _BidirectionalIterator2
>
126 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
127 copy_backward(_BidirectionalIterator1 __first
, _BidirectionalIterator1 __last
, _BidirectionalIterator2 __result
) {
128 static_assert(std::is_copy_constructible
<_BidirectionalIterator1
>::value
&&
129 std::is_copy_constructible
<_BidirectionalIterator1
>::value
,
130 "Iterators must be copy constructible.");
132 return std::__copy_backward
<_ClassicAlgPolicy
>(std::move(__first
), std::move(__last
), std::move(__result
)).second
;
135 _LIBCPP_END_NAMESPACE_STD
139 #endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H