Skip to content

Commit 36c746c

Browse files
committed
[libc++][ranges] Implement ranges::rotate.
Also fix `ranges::stable_sort` and `ranges::inplace_merge` to support proxy iterators now that their internal implementations can correctly dispatch `rotate`. Differential Revision: https://reviews.llvm.org/D130758
1 parent 42c15ca commit 36c746c

21 files changed

+418
-149
lines changed

libcxx/docs/Status/RangesAlgorithms.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Merge,set_union,Hui Xie,`D129657 <https://llvm.org/D129657>`_,✅
6868
Permutation,remove,Nikolas Klauser,`D128618 <https://llvm.org/D128618>`_,✅
6969
Permutation,remove_if,Nikolas Klauser,`D128618 <https://llvm.org/D128618>`_,✅
7070
Permutation,reverse,Nikolas Klauser,`D125752 <https://llvm.org/D125752>`_,✅
71-
Permutation,rotate,Nikolas Klauser,`D124122 <https://llvm.org/D124122>`_,Under review
71+
Permutation,rotate,Konstantin Varlamov and Nikolas Klauser,`D130758 <https://llvm.org/D130758>`_,
7272
Permutation,shuffle,Konstantin Varlamov,`D130321 <https://llvm.org/D130321>`_,✅
7373
Permutation,unique,Hui Xie,`D130404 <https://llvm.org/D130404>`_,✅
7474
Permutation,partition,Konstantin Varlamov,`D129624 <https://llvm.org/D129624>`_,✅

libcxx/include/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
set(files
22
__algorithm/adjacent_find.h
3-
__algorithm/algorithm_family.h
43
__algorithm/all_of.h
54
__algorithm/any_of.h
65
__algorithm/binary_search.h
@@ -134,6 +133,7 @@ set(files
134133
__algorithm/ranges_replace_if.h
135134
__algorithm/ranges_reverse.h
136135
__algorithm/ranges_reverse_copy.h
136+
__algorithm/ranges_rotate.h
137137
__algorithm/ranges_rotate_copy.h
138138
__algorithm/ranges_sample.h
139139
__algorithm/ranges_search.h

libcxx/include/__algorithm/algorithm_family.h

-52
This file was deleted.

libcxx/include/__algorithm/inplace_merge.h

+2-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#ifndef _LIBCPP___ALGORITHM_INPLACE_MERGE_H
1010
#define _LIBCPP___ALGORITHM_INPLACE_MERGE_H
1111

12-
#include <__algorithm/algorithm_family.h>
1312
#include <__algorithm/comp.h>
1413
#include <__algorithm/comp_ref_type.h>
1514
#include <__algorithm/iterator_operations.h>
@@ -65,7 +64,7 @@ void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1,
6564
{
6665
if (__first2 == __last2)
6766
{
68-
_AlgFamily<_AlgPolicy>::__move(__first1, __last1, __result);
67+
std::__move<_AlgPolicy>(__first1, __last1, __result);
6968
return;
7069
}
7170

@@ -185,8 +184,7 @@ void __inplace_merge(
185184
difference_type __len22 = __len2 - __len21; // distance(__m2, __last)
186185
// [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last)
187186
// swap middle two partitions
188-
// TODO(alg-policy): pass `_AlgPolicy` once it's supported by `rotate`.
189-
__middle = _VSTD::rotate(__m1, __middle, __m2);
187+
__middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first;
190188
// __len12 and __len21 now have swapped meanings
191189
// merge smaller range with recursive call and larger with tail recursion elimination
192190
if (__len11 + __len21 < __len12 + __len22)

libcxx/include/__algorithm/iterator_operations.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <__iterator/iter_swap.h>
2020
#include <__iterator/iterator_traits.h>
2121
#include <__iterator/next.h>
22+
#include <__iterator/prev.h>
2223
#include <__iterator/readable_traits.h>
2324
#include <__utility/declval.h>
2425
#include <__utility/forward.h>
@@ -53,6 +54,7 @@ struct _IterOps<_RangeAlgPolicy> {
5354
static constexpr auto __iter_move = ranges::iter_move;
5455
static constexpr auto iter_swap = ranges::iter_swap;
5556
static constexpr auto next = ranges::next;
57+
static constexpr auto prev = ranges::prev;
5658
static constexpr auto __advance_to = ranges::advance;
5759
};
5860

@@ -146,10 +148,18 @@ struct _IterOps<_ClassicAlgPolicy> {
146148
template <class _Iter>
147149
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
148150
__uncvref_t<_Iter> next(_Iter&& __it,
149-
typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){
151+
typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) {
150152
return std::next(std::forward<_Iter>(__it), __n);
151153
}
152154

155+
// prev
156+
template <class _Iter>
157+
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
158+
__uncvref_t<_Iter> prev(_Iter&& __iter,
159+
typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1) {
160+
return std::prev(std::forward<_Iter>(__iter), __n);
161+
}
162+
153163
template <class _Iter>
154164
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
155165
void __advance_to(_Iter& __first, _Iter __last) {

libcxx/include/__algorithm/move.h

+15-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _LIBCPP___ALGORITHM_MOVE_H
1010
#define _LIBCPP___ALGORITHM_MOVE_H
1111

12+
#include <__algorithm/iterator_operations.h>
1213
#include <__algorithm/unwrap_iter.h>
1314
#include <__config>
1415
#include <__iterator/iterator_traits.h>
@@ -26,18 +27,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2627

2728
// move
2829

29-
template <class _InIter, class _Sent, class _OutIter>
30+
template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
3031
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
3132
pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
3233
while (__first != __last) {
33-
*__result = std::move(*__first);
34+
*__result = _IterOps<_AlgPolicy>::__iter_move(__first);
3435
++__first;
3536
++__result;
3637
}
3738
return std::make_pair(std::move(__first), std::move(__result));
3839
}
3940

40-
template <class _InType,
41+
template <class _AlgPolicy,
42+
class _InType,
4143
class _OutType,
4244
class = __enable_if_t<is_same<typename remove_const<_InType>::type, _OutType>::value
4345
&& is_trivially_move_assignable<_OutType>::value> >
@@ -49,7 +51,7 @@ pair<_InType*, _OutType*> __move_impl(_InType* __first, _InType* __last, _OutTyp
4951
&& !is_trivially_copyable<_InType>::value
5052
#endif
5153
)
52-
return std::__move_impl<_InType*, _InType*, _OutType*>(__first, __last, __result);
54+
return std::__move_impl<_AlgPolicy, _InType*, _InType*, _OutType*>(__first, __last, __result);
5355
const size_t __n = static_cast<size_t>(__last - __first);
5456
::__builtin_memmove(__result, __first, __n * sizeof(_OutType));
5557
return std::make_pair(__first + __n, __result + __n);
@@ -65,7 +67,8 @@ template <class _Iter>
6567
struct __is_trivially_move_assignable_unwrapped
6668
: __is_trivially_move_assignable_unwrapped_impl<decltype(std::__unwrap_iter<_Iter>(std::declval<_Iter>()))> {};
6769

68-
template <class _InIter,
70+
template <class _AlgPolicy,
71+
class _InIter,
6972
class _OutIter,
7073
__enable_if_t<is_same<typename remove_const<typename iterator_traits<_InIter>::value_type>::type,
7174
typename iterator_traits<_OutIter>::value_type>::value
@@ -81,33 +84,34 @@ __move_impl(reverse_iterator<_InIter> __first,
8184
auto __last_base = std::__unwrap_iter(__last.base());
8285
auto __result_base = std::__unwrap_iter(__result.base());
8386
auto __result_first = __result_base - (__first_base - __last_base);
84-
std::__move_impl(__last_base, __first_base, __result_first);
87+
std::__move_impl<_AlgPolicy>(__last_base, __first_base, __result_first);
8588
return std::make_pair(__last, reverse_iterator<_OutIter>(std::__rewrap_iter(__result.base(), __result_first)));
8689
}
8790

88-
template <class _InIter, class _Sent, class _OutIter>
91+
template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
8992
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
9093
__enable_if_t<is_copy_constructible<_InIter>::value
9194
&& is_copy_constructible<_Sent>::value
9295
&& is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> >
9396
__move(_InIter __first, _Sent __last, _OutIter __result) {
94-
auto __ret = std::__move_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result));
97+
auto __ret = std::__move_impl<_AlgPolicy>(
98+
std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result));
9599
return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second));
96100
}
97101

98-
template <class _InIter, class _Sent, class _OutIter>
102+
template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
99103
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
100104
__enable_if_t<!is_copy_constructible<_InIter>::value
101105
|| !is_copy_constructible<_Sent>::value
102106
|| !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> >
103107
__move(_InIter __first, _Sent __last, _OutIter __result) {
104-
return std::__move_impl(std::move(__first), std::move(__last), std::move(__result));
108+
return std::__move_impl<_AlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
105109
}
106110

107111
template <class _InputIterator, class _OutputIterator>
108112
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
109113
_OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
110-
return std::__move(__first, __last, __result).second;
114+
return std::__move<_ClassicAlgPolicy>(__first, __last, __result).second;
111115
}
112116

113117
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__algorithm/move_backward.h

+24-14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
1010
#define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
1111

12+
#include <__algorithm/iterator_operations.h>
1213
#include <__algorithm/unwrap_iter.h>
1314
#include <__config>
1415
#include <__utility/move.h>
@@ -21,33 +22,33 @@
2122

2223
_LIBCPP_BEGIN_NAMESPACE_STD
2324

24-
template <class _InputIterator, class _OutputIterator>
25+
template <class _AlgPolicy, class _InputIterator, class _OutputIterator>
2526
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
2627
_OutputIterator
2728
__move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
2829
{
2930
while (__first != __last)
30-
*--__result = _VSTD::move(*--__last);
31+
*--__result = _IterOps<_AlgPolicy>::__iter_move(--__last);
3132
return __result;
3233
}
3334

34-
template <class _InputIterator, class _OutputIterator>
35+
template <class _AlgPolicy, class _InputIterator, class _OutputIterator>
3536
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
3637
_OutputIterator
37-
__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
38+
__move_backward_impl(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
3839
{
39-
return _VSTD::__move_backward_constexpr(__first, __last, __result);
40+
return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result);
4041
}
4142

42-
template <class _Tp, class _Up>
43+
template <class _AlgPolicy, class _Tp, class _Up>
4344
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
4445
typename enable_if
4546
<
4647
is_same<typename remove_const<_Tp>::type, _Up>::value &&
4748
is_trivially_move_assignable<_Up>::value,
4849
_Up*
4950
>::type
50-
__move_backward(_Tp* __first, _Tp* __last, _Up* __result)
51+
__move_backward_impl(_Tp* __first, _Tp* __last, _Up* __result)
5152
{
5253
const size_t __n = static_cast<size_t>(__last - __first);
5354
if (__n > 0)
@@ -58,22 +59,31 @@ __move_backward(_Tp* __first, _Tp* __last, _Up* __result)
5859
return __result;
5960
}
6061

61-
template <class _BidirectionalIterator1, class _BidirectionalIterator2>
62+
template <class _AlgPolicy, class _BidirectionalIterator1, class _BidirectionalIterator2>
6263
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
6364
_BidirectionalIterator2
64-
move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
65-
_BidirectionalIterator2 __result)
65+
__move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
66+
_BidirectionalIterator2 __result)
6667
{
6768
if (__libcpp_is_constant_evaluated()) {
68-
return _VSTD::__move_backward_constexpr(__first, __last, __result);
69+
return _VSTD::__move_backward_constexpr<_AlgPolicy>(__first, __last, __result);
6970
} else {
7071
return _VSTD::__rewrap_iter(__result,
71-
_VSTD::__move_backward(_VSTD::__unwrap_iter(__first),
72-
_VSTD::__unwrap_iter(__last),
73-
_VSTD::__unwrap_iter(__result)));
72+
_VSTD::__move_backward_impl<_AlgPolicy>(_VSTD::__unwrap_iter(__first),
73+
_VSTD::__unwrap_iter(__last),
74+
_VSTD::__unwrap_iter(__result)));
7475
}
7576
}
7677

78+
template <class _BidirectionalIterator1, class _BidirectionalIterator2>
79+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
80+
_BidirectionalIterator2
81+
move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
82+
_BidirectionalIterator2 __result)
83+
{
84+
return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
85+
}
86+
7787
_LIBCPP_END_NAMESPACE_STD
7888

7989
#endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H

libcxx/include/__algorithm/ranges_move.h

+2-13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define _LIBCPP___ALGORITHM_RANGES_MOVE_H
1111

1212
#include <__algorithm/in_out_result.h>
13+
#include <__algorithm/iterator_operations.h>
1314
#include <__algorithm/move.h>
1415
#include <__config>
1516
#include <__iterator/concepts.h>
@@ -36,24 +37,12 @@ namespace __move {
3637
struct __fn {
3738

3839
template <class _InIter, class _Sent, class _OutIter>
39-
requires __iter_move::__move_deref<_InIter> // check that we are allowed to std::move() the value
4040
_LIBCPP_HIDE_FROM_ABI constexpr static
4141
move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
42-
auto __ret = std::__move(std::move(__first), std::move(__last), std::move(__result));
42+
auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
4343
return {std::move(__ret.first), std::move(__ret.second)};
4444
}
4545

46-
template <class _InIter, class _Sent, class _OutIter>
47-
_LIBCPP_HIDE_FROM_ABI constexpr static
48-
move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
49-
while (__first != __last) {
50-
*__result = ranges::iter_move(__first);
51-
++__first;
52-
++__result;
53-
}
54-
return {std::move(__first), std::move(__result)};
55-
}
56-
5746
template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter>
5847
requires indirectly_movable<_InIter, _OutIter>
5948
_LIBCPP_HIDE_FROM_ABI constexpr

0 commit comments

Comments
 (0)