aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/__algorithm
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /libcxx/include/__algorithm
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'libcxx/include/__algorithm')
-rw-r--r--libcxx/include/__algorithm/adjacent_find.h33
-rw-r--r--libcxx/include/__algorithm/all_of.h2
-rw-r--r--libcxx/include/__algorithm/any_of.h2
-rw-r--r--libcxx/include/__algorithm/binary_search.h7
-rw-r--r--libcxx/include/__algorithm/clamp.h4
-rw-r--r--libcxx/include/__algorithm/comp.h50
-rw-r--r--libcxx/include/__algorithm/comp_ref_type.h27
-rw-r--r--libcxx/include/__algorithm/copy.h158
-rw-r--r--libcxx/include/__algorithm/copy_backward.h142
-rw-r--r--libcxx/include/__algorithm/copy_if.h2
-rw-r--r--libcxx/include/__algorithm/copy_move_common.h163
-rw-r--r--libcxx/include/__algorithm/copy_n.h5
-rw-r--r--libcxx/include/__algorithm/count.h2
-rw-r--r--libcxx/include/__algorithm/count_if.h2
-rw-r--r--libcxx/include/__algorithm/equal.h29
-rw-r--r--libcxx/include/__algorithm/equal_range.h13
-rw-r--r--libcxx/include/__algorithm/fill.h8
-rw-r--r--libcxx/include/__algorithm/fill_n.h7
-rw-r--r--libcxx/include/__algorithm/find.h2
-rw-r--r--libcxx/include/__algorithm/find_end.h16
-rw-r--r--libcxx/include/__algorithm/find_first_of.h14
-rw-r--r--libcxx/include/__algorithm/find_if.h2
-rw-r--r--libcxx/include/__algorithm/find_if_not.h2
-rw-r--r--libcxx/include/__algorithm/for_each.h2
-rw-r--r--libcxx/include/__algorithm/for_each_n.h3
-rw-r--r--libcxx/include/__algorithm/generate.h2
-rw-r--r--libcxx/include/__algorithm/generate_n.h3
-rw-r--r--libcxx/include/__algorithm/half_positive.h2
-rw-r--r--libcxx/include/__algorithm/in_found_result.h4
-rw-r--r--libcxx/include/__algorithm/in_fun_result.h4
-rw-r--r--libcxx/include/__algorithm/in_in_out_result.h4
-rw-r--r--libcxx/include/__algorithm/in_in_result.h4
-rw-r--r--libcxx/include/__algorithm/in_out_out_result.h4
-rw-r--r--libcxx/include/__algorithm/in_out_result.h4
-rw-r--r--libcxx/include/__algorithm/includes.h16
-rw-r--r--libcxx/include/__algorithm/inplace_merge.h98
-rw-r--r--libcxx/include/__algorithm/is_heap.h7
-rw-r--r--libcxx/include/__algorithm/is_heap_until.h9
-rw-r--r--libcxx/include/__algorithm/is_partitioned.h2
-rw-r--r--libcxx/include/__algorithm/is_permutation.h260
-rw-r--r--libcxx/include/__algorithm/is_sorted.h7
-rw-r--r--libcxx/include/__algorithm/is_sorted_until.h9
-rw-r--r--libcxx/include/__algorithm/iter_swap.h4
-rw-r--r--libcxx/include/__algorithm/iterator_operations.h102
-rw-r--r--libcxx/include/__algorithm/lexicographical_compare.h9
-rw-r--r--libcxx/include/__algorithm/lower_bound.h6
-rw-r--r--libcxx/include/__algorithm/make_heap.h13
-rw-r--r--libcxx/include/__algorithm/make_projected.h100
-rw-r--r--libcxx/include/__algorithm/max.h11
-rw-r--r--libcxx/include/__algorithm/max_element.h9
-rw-r--r--libcxx/include/__algorithm/merge.h9
-rw-r--r--libcxx/include/__algorithm/min.h11
-rw-r--r--libcxx/include/__algorithm/min_element.h11
-rw-r--r--libcxx/include/__algorithm/min_max_result.h4
-rw-r--r--libcxx/include/__algorithm/minmax.h8
-rw-r--r--libcxx/include/__algorithm/minmax_element.h8
-rw-r--r--libcxx/include/__algorithm/mismatch.h16
-rw-r--r--libcxx/include/__algorithm/move.h177
-rw-r--r--libcxx/include/__algorithm/move_backward.h156
-rw-r--r--libcxx/include/__algorithm/next_permutation.h38
-rw-r--r--libcxx/include/__algorithm/none_of.h2
-rw-r--r--libcxx/include/__algorithm/nth_element.h13
-rw-r--r--libcxx/include/__algorithm/partial_sort.h21
-rw-r--r--libcxx/include/__algorithm/partial_sort_copy.h45
-rw-r--r--libcxx/include/__algorithm/partition.h10
-rw-r--r--libcxx/include/__algorithm/partition_copy.h2
-rw-r--r--libcxx/include/__algorithm/partition_point.h2
-rw-r--r--libcxx/include/__algorithm/pop_heap.h13
-rw-r--r--libcxx/include/__algorithm/prev_permutation.h39
-rw-r--r--libcxx/include/__algorithm/push_heap.h13
-rw-r--r--libcxx/include/__algorithm/ranges_adjacent_find.h8
-rw-r--r--libcxx/include/__algorithm/ranges_all_of.h8
-rw-r--r--libcxx/include/__algorithm/ranges_any_of.h8
-rw-r--r--libcxx/include/__algorithm/ranges_binary_search.h8
-rw-r--r--libcxx/include/__algorithm/ranges_clamp.h65
-rw-r--r--libcxx/include/__algorithm/ranges_copy.h10
-rw-r--r--libcxx/include/__algorithm/ranges_copy_backward.h5
-rw-r--r--libcxx/include/__algorithm/ranges_copy_if.h4
-rw-r--r--libcxx/include/__algorithm/ranges_copy_n.h7
-rw-r--r--libcxx/include/__algorithm/ranges_count.h8
-rw-r--r--libcxx/include/__algorithm/ranges_count_if.h8
-rw-r--r--libcxx/include/__algorithm/ranges_equal.h8
-rw-r--r--libcxx/include/__algorithm/ranges_equal_range.h9
-rw-r--r--libcxx/include/__algorithm/ranges_fill.h4
-rw-r--r--libcxx/include/__algorithm/ranges_fill_n.h4
-rw-r--r--libcxx/include/__algorithm/ranges_find.h8
-rw-r--r--libcxx/include/__algorithm/ranges_find_end.h9
-rw-r--r--libcxx/include/__algorithm/ranges_find_first_of.h8
-rw-r--r--libcxx/include/__algorithm/ranges_find_if.h8
-rw-r--r--libcxx/include/__algorithm/ranges_find_if_not.h8
-rw-r--r--libcxx/include/__algorithm/ranges_for_each.h4
-rw-r--r--libcxx/include/__algorithm/ranges_for_each_n.h4
-rw-r--r--libcxx/include/__algorithm/ranges_generate.h4
-rw-r--r--libcxx/include/__algorithm/ranges_generate_n.h4
-rw-r--r--libcxx/include/__algorithm/ranges_includes.h8
-rw-r--r--libcxx/include/__algorithm/ranges_inplace_merge.h56
-rw-r--r--libcxx/include/__algorithm/ranges_is_heap.h10
-rw-r--r--libcxx/include/__algorithm/ranges_is_heap_until.h10
-rw-r--r--libcxx/include/__algorithm/ranges_is_partitioned.h8
-rw-r--r--libcxx/include/__algorithm/ranges_is_permutation.h89
-rw-r--r--libcxx/include/__algorithm/ranges_is_sorted.h8
-rw-r--r--libcxx/include/__algorithm/ranges_is_sorted_until.h8
-rw-r--r--libcxx/include/__algorithm/ranges_iterator_concept.h8
-rw-r--r--libcxx/include/__algorithm/ranges_lexicographical_compare.h8
-rw-r--r--libcxx/include/__algorithm/ranges_lower_bound.h8
-rw-r--r--libcxx/include/__algorithm/ranges_make_heap.h6
-rw-r--r--libcxx/include/__algorithm/ranges_max.h10
-rw-r--r--libcxx/include/__algorithm/ranges_max_element.h8
-rw-r--r--libcxx/include/__algorithm/ranges_merge.h8
-rw-r--r--libcxx/include/__algorithm/ranges_min.h10
-rw-r--r--libcxx/include/__algorithm/ranges_min_element.h8
-rw-r--r--libcxx/include/__algorithm/ranges_minmax.h11
-rw-r--r--libcxx/include/__algorithm/ranges_minmax_element.h8
-rw-r--r--libcxx/include/__algorithm/ranges_mismatch.h8
-rw-r--r--libcxx/include/__algorithm/ranges_move.h20
-rw-r--r--libcxx/include/__algorithm/ranges_move_backward.h14
-rw-r--r--libcxx/include/__algorithm/ranges_next_permutation.h73
-rw-r--r--libcxx/include/__algorithm/ranges_none_of.h8
-rw-r--r--libcxx/include/__algorithm/ranges_nth_element.h6
-rw-r--r--libcxx/include/__algorithm/ranges_partial_sort.h7
-rw-r--r--libcxx/include/__algorithm/ranges_partial_sort_copy.h24
-rw-r--r--libcxx/include/__algorithm/ranges_partition.h9
-rw-r--r--libcxx/include/__algorithm/ranges_partition_copy.h6
-rw-r--r--libcxx/include/__algorithm/ranges_partition_point.h4
-rw-r--r--libcxx/include/__algorithm/ranges_pop_heap.h6
-rw-r--r--libcxx/include/__algorithm/ranges_prev_permutation.h77
-rw-r--r--libcxx/include/__algorithm/ranges_push_heap.h6
-rw-r--r--libcxx/include/__algorithm/ranges_remove.h8
-rw-r--r--libcxx/include/__algorithm/ranges_remove_copy.h59
-rw-r--r--libcxx/include/__algorithm/ranges_remove_copy_if.h62
-rw-r--r--libcxx/include/__algorithm/ranges_remove_if.h8
-rw-r--r--libcxx/include/__algorithm/ranges_replace.h4
-rw-r--r--libcxx/include/__algorithm/ranges_replace_copy.h73
-rw-r--r--libcxx/include/__algorithm/ranges_replace_copy_if.h76
-rw-r--r--libcxx/include/__algorithm/ranges_replace_if.h4
-rw-r--r--libcxx/include/__algorithm/ranges_reverse.h4
-rw-r--r--libcxx/include/__algorithm/ranges_reverse_copy.h4
-rw-r--r--libcxx/include/__algorithm/ranges_rotate.h71
-rw-r--r--libcxx/include/__algorithm/ranges_rotate_copy.h4
-rw-r--r--libcxx/include/__algorithm/ranges_sample.h74
-rw-r--r--libcxx/include/__algorithm/ranges_search.h9
-rw-r--r--libcxx/include/__algorithm/ranges_search_n.h17
-rw-r--r--libcxx/include/__algorithm/ranges_set_difference.h12
-rw-r--r--libcxx/include/__algorithm/ranges_set_intersection.h6
-rw-r--r--libcxx/include/__algorithm/ranges_set_symmetric_difference.h11
-rw-r--r--libcxx/include/__algorithm/ranges_set_union.h11
-rw-r--r--libcxx/include/__algorithm/ranges_shuffle.h38
-rw-r--r--libcxx/include/__algorithm/ranges_sort.h6
-rw-r--r--libcxx/include/__algorithm/ranges_sort_heap.h6
-rw-r--r--libcxx/include/__algorithm/ranges_stable_partition.h8
-rw-r--r--libcxx/include/__algorithm/ranges_stable_sort.h6
-rw-r--r--libcxx/include/__algorithm/ranges_swap_ranges.h15
-rw-r--r--libcxx/include/__algorithm/ranges_transform.h4
-rw-r--r--libcxx/include/__algorithm/ranges_unique.h51
-rw-r--r--libcxx/include/__algorithm/ranges_unique_copy.h78
-rw-r--r--libcxx/include/__algorithm/ranges_upper_bound.h8
-rw-r--r--libcxx/include/__algorithm/remove.h2
-rw-r--r--libcxx/include/__algorithm/remove_copy.h2
-rw-r--r--libcxx/include/__algorithm/remove_copy_if.h2
-rw-r--r--libcxx/include/__algorithm/remove_if.h2
-rw-r--r--libcxx/include/__algorithm/replace.h2
-rw-r--r--libcxx/include/__algorithm/replace_copy.h2
-rw-r--r--libcxx/include/__algorithm/replace_copy_if.h2
-rw-r--r--libcxx/include/__algorithm/replace_if.h2
-rw-r--r--libcxx/include/__algorithm/reverse.h29
-rw-r--r--libcxx/include/__algorithm/reverse_copy.h2
-rw-r--r--libcxx/include/__algorithm/rotate.h77
-rw-r--r--libcxx/include/__algorithm/rotate_copy.h2
-rw-r--r--libcxx/include/__algorithm/sample.h48
-rw-r--r--libcxx/include/__algorithm/search.h18
-rw-r--r--libcxx/include/__algorithm/search_n.h16
-rw-r--r--libcxx/include/__algorithm/set_difference.h18
-rw-r--r--libcxx/include/__algorithm/set_intersection.h11
-rw-r--r--libcxx/include/__algorithm/set_symmetric_difference.h19
-rw-r--r--libcxx/include/__algorithm/set_union.h19
-rw-r--r--libcxx/include/__algorithm/shuffle.h25
-rw-r--r--libcxx/include/__algorithm/sift_down.h8
-rw-r--r--libcxx/include/__algorithm/sort.h644
-rw-r--r--libcxx/include/__algorithm/sort_heap.h13
-rw-r--r--libcxx/include/__algorithm/stable_partition.h19
-rw-r--r--libcxx/include/__algorithm/stable_sort.h15
-rw-r--r--libcxx/include/__algorithm/swap_ranges.h39
-rw-r--r--libcxx/include/__algorithm/transform.h4
-rw-r--r--libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h62
-rw-r--r--libcxx/include/__algorithm/unique.h47
-rw-r--r--libcxx/include/__algorithm/unique_copy.h146
-rw-r--r--libcxx/include/__algorithm/unwrap_iter.h6
-rw-r--r--libcxx/include/__algorithm/unwrap_range.h97
-rw-r--r--libcxx/include/__algorithm/upper_bound.h6
189 files changed, 3230 insertions, 1680 deletions
diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h
index 83d8c260f27a..30df4a976f3d 100644
--- a/libcxx/include/__algorithm/adjacent_find.h
+++ b/libcxx/include/__algorithm/adjacent_find.h
@@ -11,8 +11,10 @@
#define _LIBCPP___ALGORITHM_ADJACENT_FIND_H
#include <__algorithm/comp.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -20,25 +22,30 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+template <class _Iter, class _Sent, class _BinaryPredicate>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
+__adjacent_find(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
+ if (__first == __last)
+ return __first;
+ _Iter __i = __first;
+ while (++__i != __last) {
+ if (__pred(*__first, *__i))
+ return __first;
+ __first = __i;
+ }
+ return __i;
+}
+
template <class _ForwardIterator, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
- if (__first != __last) {
- _ForwardIterator __i = __first;
- while (++__i != __last) {
- if (__pred(*__first, *__i))
- return __first;
- __first = __i;
- }
- }
- return __last;
+ return std::__adjacent_find(std::move(__first), std::move(__last), __pred);
}
template <class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
adjacent_find(_ForwardIterator __first, _ForwardIterator __last) {
- typedef typename iterator_traits<_ForwardIterator>::value_type __v;
- return _VSTD::adjacent_find(__first, __last, __equal_to<__v>());
+ return std::adjacent_find(std::move(__first), std::move(__last), __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h
index 3af32a577504..284c34ffcda9 100644
--- a/libcxx/include/__algorithm/all_of.h
+++ b/libcxx/include/__algorithm/all_of.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (!__pred(*__first))
diff --git a/libcxx/include/__algorithm/any_of.h b/libcxx/include/__algorithm/any_of.h
index 6fe6a0b6b3c4..fe0882816b9b 100644
--- a/libcxx/include/__algorithm/any_of.h
+++ b/libcxx/include/__algorithm/any_of.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (__pred(*__first))
diff --git a/libcxx/include/__algorithm/binary_search.h b/libcxx/include/__algorithm/binary_search.h
index a44007237850..8f958c2c1ad8 100644
--- a/libcxx/include/__algorithm/binary_search.h
+++ b/libcxx/include/__algorithm/binary_search.h
@@ -23,18 +23,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp)
{
- using _Comp_ref = typename __comp_ref_type<_Compare>::type;
- __first = std::lower_bound<_ForwardIterator, _Tp, _Comp_ref>(__first, __last, __value, __comp);
+ __first = std::lower_bound<_ForwardIterator, _Tp, __comp_ref_type<_Compare> >(__first, __last, __value, __comp);
return __first != __last && !__comp(__value, *__first);
}
template <class _ForwardIterator, class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
{
diff --git a/libcxx/include/__algorithm/clamp.h b/libcxx/include/__algorithm/clamp.h
index b3762b85a0bc..30ddbdce64a9 100644
--- a/libcxx/include/__algorithm/clamp.h
+++ b/libcxx/include/__algorithm/clamp.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 14
template<class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+_LIBCPP_INLINE_VISIBILITY constexpr
const _Tp&
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
{
@@ -33,7 +33,7 @@ clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
template<class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+_LIBCPP_INLINE_VISIBILITY constexpr
const _Tp&
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi)
{
diff --git a/libcxx/include/__algorithm/comp.h b/libcxx/include/__algorithm/comp.h
index 62c06ae57f23..af8eb7b5d76b 100644
--- a/libcxx/include/__algorithm/comp.h
+++ b/libcxx/include/__algorithm/comp.h
@@ -17,73 +17,47 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-// I'd like to replace these with _VSTD::equal_to<void>, but can't because:
-// * That only works with C++14 and later, and
-// * We haven't included <functional> here.
-template <class _T1, class _T2 = _T1>
-struct __equal_to
-{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<_T1, _T1>
-{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
- bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<const _T1, _T1>
-{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
- bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
-};
-
-template <class _T1>
-struct __equal_to<_T1, const _T1>
-{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
- bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
+struct __equal_to {
+ template <class _T1, class _T2>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator()(const _T1& __x, const _T2& __y) const {
+ return __x == __y;
+ }
};
template <class _T1, class _T2 = _T1>
struct __less
{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T1& __x, const _T2& __y) const {return __x < __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T2& __x, const _T1& __y) const {return __x < __y;}
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T2& __x, const _T2& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<_T1, _T1>
{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<const _T1, _T1>
{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
template <class _T1>
struct __less<_T1, const _T1>
{
- _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}
};
diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h
index 4719871461cf..f2338e144688 100644
--- a/libcxx/include/__algorithm/comp_ref_type.h
+++ b/libcxx/include/__algorithm/comp_ref_type.h
@@ -23,11 +23,11 @@ template <class _Compare>
struct __debug_less
{
_Compare &__comp_;
- _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_CONSTEXPR_SINCE_CXX14
__debug_less(_Compare& __c) : __comp_(__c) {}
template <class _Tp, class _Up>
- _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(const _Tp& __x, const _Up& __y)
{
bool __r = __comp_(__x, __y);
@@ -37,7 +37,7 @@ struct __debug_less
}
template <class _Tp, class _Up>
- _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(_Tp& __x, _Up& __y)
{
bool __r = __comp_(__x, __y);
@@ -47,10 +47,10 @@ struct __debug_less
}
template <class _LHS, class _RHS>
- _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_CONSTEXPR_SINCE_CXX14
inline _LIBCPP_INLINE_VISIBILITY
- decltype((void)declval<_Compare&>()(
- declval<_LHS &>(), declval<_RHS &>()))
+ decltype((void)std::declval<_Compare&>()(
+ std::declval<_LHS &>(), std::declval<_RHS &>()))
__do_compare_assert(int, _LHS & __l, _RHS & __r) {
_LIBCPP_DEBUG_ASSERT(!__comp_(__l, __r),
"Comparator does not induce a strict weak ordering");
@@ -59,21 +59,20 @@ struct __debug_less
}
template <class _LHS, class _RHS>
- _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_CONSTEXPR_SINCE_CXX14
inline _LIBCPP_INLINE_VISIBILITY
void __do_compare_assert(long, _LHS &, _RHS &) {}
};
-template <class _Comp>
-struct __comp_ref_type {
- // Pass the comparator by lvalue reference. Or in debug mode, using a
- // debugging wrapper that stores a reference.
+// Pass the comparator by lvalue reference. Or in debug mode, using a
+// debugging wrapper that stores a reference.
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
- typedef __debug_less<_Comp> type;
+template <class _Comp>
+using __comp_ref_type = __debug_less<_Comp>;
#else
- typedef _Comp& type;
+template <class _Comp>
+using __comp_ref_type = _Comp&;
#endif
-};
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h
index 5428baa68859..193a6df31656 100644
--- a/libcxx/include/__algorithm/copy.h
+++ b/libcxx/include/__algorithm/copy.h
@@ -9,98 +9,118 @@
#ifndef _LIBCPP___ALGORITHM_COPY_H
#define _LIBCPP___ALGORITHM_COPY_H
-#include <__algorithm/unwrap_iter.h>
+#include <__algorithm/copy_move_common.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/min.h>
#include <__config>
-#include <__iterator/iterator_traits.h>
-#include <__iterator/reverse_iterator.h>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/common_type.h>
#include <__utility/move.h>
#include <__utility/pair.h>
-#include <cstring>
-#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
-// copy
+template <class, class _InIter, class _Sent, class _OutIter>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter);
+
+template <class _AlgPolicy>
+struct __copy_loop {
+ template <class _InIter, class _Sent, class _OutIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result) const {
+ while (__first != __last) {
+ *__result = *__first;
+ ++__first;
+ ++__result;
+ }
-template <class _InIter, class _Sent, class _OutIter>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InIter, _OutIter> __copy_impl(_InIter __first, _Sent __last, _OutIter __result) {
- while (__first != __last) {
- *__result = *__first;
- ++__first;
- ++__result;
+ return std::make_pair(std::move(__first), std::move(__result));
}
- return pair<_InIter, _OutIter>(std::move(__first), std::move(__result));
-}
-template <class _InValueT,
- class _OutValueT,
- class = __enable_if_t<is_same<typename remove_const<_InValueT>::type, _OutValueT>::value
- && is_trivially_copy_assignable<_OutValueT>::value> >
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InValueT*, _OutValueT*> __copy_impl(_InValueT* __first, _InValueT* __last, _OutValueT* __result) {
- if (__libcpp_is_constant_evaluated()
-// TODO: Remove this once GCC supports __builtin_memmove during constant evaluation
-#ifndef _LIBCPP_COMPILER_GCC
- && !is_trivially_copyable<_InValueT>::value
-#endif
- )
- return std::__copy_impl<_InValueT*, _InValueT*, _OutValueT*>(__first, __last, __result);
- const size_t __n = static_cast<size_t>(__last - __first);
- if (__n > 0)
- ::__builtin_memmove(__result, __first, __n * sizeof(_OutValueT));
- return std::make_pair(__first + __n, __result + __n);
-}
+ template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) const {
+ using _Traits = __segmented_iterator_traits<_InIter>;
+ auto __sfirst = _Traits::__segment(__first);
+ auto __slast = _Traits::__segment(__last);
+ if (__sfirst == __slast) {
+ auto __iters = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
+ return std::make_pair(__last, std::move(__iters.second));
+ }
-template <class _InIter, class _OutIter,
- __enable_if_t<is_same<typename remove_const<__iter_value_type<_InIter> >::type, __iter_value_type<_OutIter> >::value
- && __is_cpp17_contiguous_iterator<typename _InIter::iterator_type>::value
- && __is_cpp17_contiguous_iterator<typename _OutIter::iterator_type>::value
- && is_trivially_copy_assignable<__iter_value_type<_OutIter> >::value
- && __is_reverse_iterator<_InIter>::value
- && __is_reverse_iterator<_OutIter>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InIter, _OutIter>
-__copy_impl(_InIter __first, _InIter __last, _OutIter __result) {
- auto __first_base = std::__unwrap_iter(__first.base());
- auto __last_base = std::__unwrap_iter(__last.base());
- auto __result_base = std::__unwrap_iter(__result.base());
- auto __result_first = __result_base - (__first_base - __last_base);
- std::__copy_impl(__last_base, __first_base, __result_first);
- return std::make_pair(__last, _OutIter(std::__rewrap_iter(__result.base(), __result_first)));
-}
+ __result = std::__copy<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second;
+ ++__sfirst;
+ while (__sfirst != __slast) {
+ __result =
+ std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second;
+ ++__sfirst;
+ }
+ __result =
+ std::__copy<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second;
+ return std::make_pair(__last, std::move(__result));
+ }
-template <class _InIter, class _Sent, class _OutIter,
- __enable_if_t<!(is_copy_constructible<_InIter>::value
- && is_copy_constructible<_Sent>::value
- && is_copy_constructible<_OutIter>::value), int> = 0 >
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InIter, _OutIter> __copy(_InIter __first, _Sent __last, _OutIter __result) {
- return std::__copy_impl(std::move(__first), std::move(__last), std::move(__result));
-}
+ template <class _InIter,
+ class _OutIter,
+ __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value &&
+ !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) {
+ using _Traits = __segmented_iterator_traits<_OutIter>;
+ using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;
-template <class _InIter, class _Sent, class _OutIter,
- __enable_if_t<is_copy_constructible<_InIter>::value
- && is_copy_constructible<_Sent>::value
- && is_copy_constructible<_OutIter>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InIter, _OutIter>
+ if (__first == __last)
+ return std::make_pair(std::move(__first), std::move(__result));
+
+ auto __local_first = _Traits::__local(__result);
+ auto __segment_iterator = _Traits::__segment(__result);
+ while (true) {
+ auto __local_last = _Traits::__end(__segment_iterator);
+ auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
+ auto __iters = std::__copy<_AlgPolicy>(__first, __first + __size, __local_first);
+ __first = std::move(__iters.first);
+
+ if (__first == __last)
+ return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second)));
+
+ __local_first = _Traits::__begin(++__segment_iterator);
+ }
+ }
+};
+
+struct __copy_trivial {
+ // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
+ template <class _In, class _Out,
+ __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+ operator()(_In* __first, _In* __last, _Out* __result) const {
+ return std::__copy_trivial_impl(__first, __last, __result);
+ }
+};
+
+template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
+pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
__copy(_InIter __first, _Sent __last, _OutIter __result) {
- auto __ret = std::__copy_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result));
- return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second));
+ return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>(
+ std::move(__first), std::move(__last), std::move(__result));
}
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_OutputIterator
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
- return std::__copy(__first, __last, __result).second;
+ return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second;
}
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_COPY_H
diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h
index 26b8c4d791fd..bb2a4328781c 100644
--- a/libcxx/include/__algorithm/copy_backward.h
+++ b/libcxx/include/__algorithm/copy_backward.h
@@ -9,53 +9,135 @@
#ifndef _LIBCPP___ALGORITHM_COPY_BACKWARD_H
#define _LIBCPP___ALGORITHM_COPY_BACKWARD_H
-#include <__algorithm/copy.h>
+#include <__algorithm/copy_move_common.h>
#include <__algorithm/iterator_operations.h>
-#include <__algorithm/ranges_copy.h>
-#include <__algorithm/unwrap_iter.h>
-#include <__concepts/same_as.h>
+#include <__algorithm/min.h>
#include <__config>
-#include <__iterator/iterator_traits.h>
-#include <__iterator/reverse_iterator.h>
-#include <__ranges/subrange.h>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/is_copy_constructible.h>
#include <__utility/move.h>
#include <__utility/pair.h>
-#include <cstring>
-#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _AlgPolicy, class _InputIterator, class _OutputIterator,
- __enable_if_t<is_same<_AlgPolicy, _ClassicAlgPolicy>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 pair<_InputIterator, _OutputIterator>
-__copy_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
- auto __ret = std::__copy(
- __unconstrained_reverse_iterator<_InputIterator>(__last),
- __unconstrained_reverse_iterator<_InputIterator>(__first),
- __unconstrained_reverse_iterator<_OutputIterator>(__result));
- return pair<_InputIterator, _OutputIterator>(__ret.first.base(), __ret.second.base());
-}
+template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
+__copy_backward(_InIter __first, _Sent __last, _OutIter __result);
+
+template <class _AlgPolicy>
+struct __copy_backward_loop {
+ template <class _InIter, class _Sent, class _OutIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result) const {
+ auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
+ auto __original_last_iter = __last_iter;
+
+ while (__first != __last_iter) {
+ *--__result = *--__last_iter;
+ }
+
+ return std::make_pair(std::move(__original_last_iter), std::move(__result));
+ }
+
+ template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) const {
+ using _Traits = __segmented_iterator_traits<_InIter>;
+ auto __sfirst = _Traits::__segment(__first);
+ auto __slast = _Traits::__segment(__last);
+ if (__sfirst == __slast) {
+ auto __iters =
+ std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
+ return std::make_pair(__last, __iters.second);
+ }
+
+ __result =
+ std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
+ .second;
+ --__slast;
+ while (__sfirst != __slast) {
+ __result =
+ std::__copy_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
+ .second;
+ --__slast;
+ }
+ __result = std::__copy_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
+ .second;
+ return std::make_pair(__last, std::move(__result));
+ }
+
+ template <class _InIter,
+ class _OutIter,
+ __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value &&
+ !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) {
+ using _Traits = __segmented_iterator_traits<_OutIter>;
+ auto __orig_last = __last;
+ auto __segment_iterator = _Traits::__segment(__result);
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
-template <class _AlgPolicy, class _Iter1, class _Sent1, class _Iter2,
- __enable_if_t<is_same<_AlgPolicy, _RangeAlgPolicy>::value, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr pair<_Iter1, _Iter2> __copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) {
- auto __reverse_range = std::__reverse_range(std::ranges::subrange(std::move(__first), std::move(__last)));
- auto __ret = ranges::copy(std::move(__reverse_range), std::make_reverse_iterator(__result));
- return std::make_pair(__ret.in.base(), __ret.out.base());
+ // When the range contains no elements, __result might not be a valid iterator
+ if (__first == __last)
+ return std::make_pair(__first, __result);
+
+ auto __local_last = _Traits::__local(__result);
+ while (true) {
+ using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;
+
+ auto __local_first = _Traits::__begin(__segment_iterator);
+ auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
+ auto __iter = std::__copy_backward<_AlgPolicy>(__last - __size, __last, __local_last).second;
+ __last -= __size;
+
+ if (__first == __last)
+ return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter)));
+ --__segment_iterator;
+ __local_last = _Traits::__end(__segment_iterator);
+ }
+ }
+};
+
+struct __copy_backward_trivial {
+ // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
+ template <class _In, class _Out,
+ __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+ operator()(_In* __first, _In* __last, _Out* __result) const {
+ return std::__copy_backward_trivial_impl(__first, __last, __result);
+ }
+};
+
+template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>
+__copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) {
+ return std::__dispatch_copy_or_move<_AlgPolicy, __copy_backward_loop<_AlgPolicy>, __copy_backward_trivial>(
+ std::move(__first), std::move(__last), std::move(__result));
}
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
template <class _BidirectionalIterator1, class _BidirectionalIterator2>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _BidirectionalIterator2
-copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {
- return std::__copy_backward<_ClassicAlgPolicy>(__first, __last, __result).second;
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+_BidirectionalIterator2
+copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
+ _BidirectionalIterator2 __result)
+{
+ static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&
+ std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible.");
+
+ return std::__copy_backward<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__result)).second;
}
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_COPY_BACKWARD_H
diff --git a/libcxx/include/__algorithm/copy_if.h b/libcxx/include/__algorithm/copy_if.h
index 9c3cd29e2413..a5938b8719da 100644
--- a/libcxx/include/__algorithm/copy_if.h
+++ b/libcxx/include/__algorithm/copy_if.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template<class _InputIterator, class _OutputIterator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
copy_if(_InputIterator __first, _InputIterator __last,
_OutputIterator __result, _Predicate __pred)
diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h
new file mode 100644
index 000000000000..b88c14911b9b
--- /dev/null
+++ b/libcxx/include/__algorithm/copy_move_common.h
@@ -0,0 +1,163 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
+#define _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
+
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/unwrap_iter.h>
+#include <__algorithm/unwrap_range.h>
+#include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__memory/pointer_traits.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_always_bitcastable.h>
+#include <__type_traits/is_constant_evaluated.h>
+#include <__type_traits/is_copy_constructible.h>
+#include <__type_traits/is_trivially_assignable.h>
+#include <__type_traits/is_trivially_copyable.h>
+#include <__type_traits/is_volatile.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+#include <cstddef>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// Type traits.
+
+template <class _From, class _To>
+struct __can_lower_copy_assignment_to_memmove {
+ static const bool value =
+ // If the types are always bitcastable, it's valid to do a bitwise copy between them.
+ __is_always_bitcastable<_From, _To>::value &&
+ // Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays).
+ is_trivially_assignable<_To&, const _From&>::value &&
+ // `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case.
+ !is_volatile<_From>::value &&
+ !is_volatile<_To>::value;
+};
+
+template <class _From, class _To>
+struct __can_lower_move_assignment_to_memmove {
+ static const bool value =
+ __is_always_bitcastable<_From, _To>::value &&
+ is_trivially_assignable<_To&, _From&&>::value &&
+ !is_volatile<_From>::value &&
+ !is_volatile<_To>::value;
+};
+
+// `memmove` algorithms implementation.
+
+template <class _In, class _Out>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+__copy_trivial_impl(_In* __first, _In* __last, _Out* __result) {
+ const size_t __n = static_cast<size_t>(__last - __first);
+ ::__builtin_memmove(__result, __first, __n * sizeof(_Out));
+
+ return std::make_pair(__last, __result + __n);
+}
+
+template <class _In, class _Out>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+__copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) {
+ const size_t __n = static_cast<size_t>(__last - __first);
+ __result -= __n;
+
+ ::__builtin_memmove(__result, __first, __n * sizeof(_Out));
+
+ return std::make_pair(__last, __result);
+}
+
+// Iterator unwrapping and dispatching to the correct overload.
+
+template <class _F1, class _F2>
+struct __overload : _F1, _F2 {
+ using _F1::operator();
+ using _F2::operator();
+};
+
+template <class _InIter, class _Sent, class _OutIter, class = void>
+struct __can_rewrap : false_type {};
+
+template <class _InIter, class _Sent, class _OutIter>
+struct __can_rewrap<_InIter,
+ _Sent,
+ _OutIter,
+ // Note that sentinels are always copy-constructible.
+ __enable_if_t< is_copy_constructible<_InIter>::value &&
+ is_copy_constructible<_OutIter>::value > > : true_type {};
+
+template <class _Algorithm,
+ class _InIter,
+ class _Sent,
+ class _OutIter,
+ __enable_if_t<__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
+__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
+ auto __range = std::__unwrap_range(__first, std::move(__last));
+ auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first));
+ return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)),
+ std::__rewrap_iter(std::move(__out_first), std::move(__result.second)));
+}
+
+template <class _Algorithm,
+ class _InIter,
+ class _Sent,
+ class _OutIter,
+ __enable_if_t<!__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
+__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
+ return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first));
+}
+
+template <class _IterOps, class _InValue, class _OutIter, class = void>
+struct __can_copy_without_conversion : false_type {};
+
+template <class _IterOps, class _InValue, class _OutIter>
+struct __can_copy_without_conversion<
+ _IterOps,
+ _InValue,
+ _OutIter,
+ __enable_if_t<is_same<_InValue, typename _IterOps::template __value_type<_OutIter> >::value> > : true_type {};
+
+template <class _AlgPolicy,
+ class _NaiveAlgorithm,
+ class _OptimizedAlgorithm,
+ class _InIter,
+ class _Sent,
+ class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
+__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) {
+#ifdef _LIBCPP_COMPILER_GCC
+ // GCC doesn't support `__builtin_memmove` during constant evaluation.
+ if (__libcpp_is_constant_evaluated()) {
+ return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
+ }
+#else
+ // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is
+ // insufficient). Also, conversions are not supported.
+ if (__libcpp_is_constant_evaluated()) {
+ using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>;
+ if (!is_trivially_copyable<_InValue>::value ||
+ !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) {
+ return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
+ }
+ }
+#endif // _LIBCPP_COMPILER_GCC
+
+ using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>;
+ return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first));
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
diff --git a/libcxx/include/__algorithm/copy_n.h b/libcxx/include/__algorithm/copy_n.h
index 8b915af63c0d..b08bbdfb9b7e 100644
--- a/libcxx/include/__algorithm/copy_n.h
+++ b/libcxx/include/__algorithm/copy_n.h
@@ -12,6 +12,7 @@
#include <__algorithm/copy.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__utility/convert_to_integral.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -21,7 +22,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template<class _InputIterator, class _Size, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename enable_if
<
__is_cpp17_input_iterator<_InputIterator>::value &&
@@ -47,7 +48,7 @@ copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result)
}
template<class _InputIterator, class _Size, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename enable_if
<
__is_cpp17_random_access_iterator<_InputIterator>::value,
diff --git a/libcxx/include/__algorithm/count.h b/libcxx/include/__algorithm/count.h
index 5b546934038d..6c8c7fda35df 100644
--- a/libcxx/include/__algorithm/count.h
+++ b/libcxx/include/__algorithm/count.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename iterator_traits<_InputIterator>::difference_type
count(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
typename iterator_traits<_InputIterator>::difference_type __r(0);
diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index 1ec2d83394e1..b96521fe0a85 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
typename iterator_traits<_InputIterator>::difference_type __r(0);
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index ca1bc6bc5665..cf37f46aaf69 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -22,7 +22,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
for (; __first1 != __last1; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2))
@@ -31,16 +31,14 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
}
template <class _InputIterator1, class _InputIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
- typedef typename iterator_traits<_InputIterator1>::value_type __v1;
- typedef typename iterator_traits<_InputIterator2>::value_type __v2;
- return _VSTD::equal(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+ return std::equal(__first1, __last1, __first2, __equal_to());
}
#if _LIBCPP_STD_VER > 11
template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2,
_BinaryPredicate __pred, input_iterator_tag, input_iterator_tag) {
for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
@@ -50,7 +48,7 @@ __equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fir
}
template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _RandomAccessIterator2 __first2,
_RandomAccessIterator2 __last2, _BinaryPredicate __pred, random_access_iterator_tag,
random_access_iterator_tag) {
@@ -61,7 +59,7 @@ __equal(_RandomAccessIterator1 __first1, _RandomAccessIterator1 __last1, _Random
}
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2,
_BinaryPredicate __pred) {
return _VSTD::__equal<_BinaryPredicate&>(
@@ -70,13 +68,16 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
}
template <class _InputIterator1, class _InputIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
- typedef typename iterator_traits<_InputIterator1>::value_type __v1;
- typedef typename iterator_traits<_InputIterator2>::value_type __v2;
- return _VSTD::__equal(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(),
- typename iterator_traits<_InputIterator1>::iterator_category(),
- typename iterator_traits<_InputIterator2>::iterator_category());
+ return std::__equal(
+ __first1,
+ __last1,
+ __first2,
+ __last2,
+ __equal_to(),
+ typename iterator_traits<_InputIterator1>::iterator_category(),
+ typename iterator_traits<_InputIterator2>::iterator_category());
}
#endif
diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h
index b11165baf384..2075b03412e3 100644
--- a/libcxx/include/__algorithm/equal_range.h
+++ b/libcxx/include/__algorithm/equal_range.h
@@ -34,7 +34,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_Iter, _Iter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter, _Iter>
__equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) {
auto __len = _IterOps<_AlgPolicy>::distance(__first, __last);
_Iter __end = _IterOps<_AlgPolicy>::next(__first, __last);
@@ -58,19 +58,22 @@ __equal_range(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
}
template <class _ForwardIterator, class _Tp, class _Compare>
-_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value,
"The comparator has to be callable");
static_assert(is_copy_constructible<_ForwardIterator>::value,
"Iterator has to be copy constructible");
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
return std::__equal_range<_ClassicAlgPolicy>(
- std::move(__first), std::move(__last), __value, static_cast<_Comp_ref>(__comp), std::__identity());
+ std::move(__first),
+ std::move(__last),
+ __value,
+ static_cast<__comp_ref_type<_Compare> >(__comp),
+ std::__identity());
}
template <class _ForwardIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
equal_range(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
return std::equal_range(
std::move(__first),
diff --git a/libcxx/include/__algorithm/fill.h b/libcxx/include/__algorithm/fill.h
index ec9968fdb8b3..76cf4a1477a6 100644
--- a/libcxx/include/__algorithm/fill.h
+++ b/libcxx/include/__algorithm/fill.h
@@ -20,8 +20,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+// fill isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
+
template <class _ForwardIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
__fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, forward_iterator_tag)
{
@@ -30,7 +32,7 @@ __fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, fo
}
template <class _RandomAccessIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
__fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& __value, random_access_iterator_tag)
{
@@ -38,7 +40,7 @@ __fill(_RandomAccessIterator __first, _RandomAccessIterator __last, const _Tp& _
}
template <class _ForwardIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
{
diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h
index 7482a4188dd5..fe58c8d64178 100644
--- a/libcxx/include/__algorithm/fill_n.h
+++ b/libcxx/include/__algorithm/fill_n.h
@@ -11,6 +11,7 @@
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__utility/convert_to_integral.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -19,8 +20,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+// fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset.
+
template <class _OutputIterator, class _Size, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value)
{
@@ -30,7 +33,7 @@ __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value)
}
template <class _OutputIterator, class _Size, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
fill_n(_OutputIterator __first, _Size __n, const _Tp& __value)
{
diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h
index ab37d81262f0..e51dc9bb160a 100644
--- a/libcxx/include/__algorithm/find.h
+++ b/libcxx/include/__algorithm/find.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find(_InputIterator __first, _InputIterator __last, const _Tp& __value) {
for (; __first != __last; ++__first)
if (*__first == __value)
diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h
index 65e9f29b1c1f..e2fee6b3c459 100644
--- a/libcxx/include/__algorithm/find_end.h
+++ b/libcxx/include/__algorithm/find_end.h
@@ -37,7 +37,7 @@ template <
class _Pred,
class _Proj1,
class _Proj2>
-_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_AFTER_CXX11 pair<_Iter1, _Iter1> __find_end_impl(
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __find_end_impl(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
@@ -91,7 +91,7 @@ template <
class _Sent2,
class _Proj1,
class _Proj2>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter1 __find_end(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter1 __find_end(
_Iter1 __first1,
_Sent1 __sent1,
_Iter2 __first2,
@@ -144,7 +144,7 @@ template <
class _Sent2,
class _Proj1,
class _Proj2>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter1 __find_end(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter1 __find_end(
_Iter1 __first1,
_Sent1 __sent1,
_Iter2 __first2,
@@ -189,7 +189,7 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _Iter1 __find_end(
}
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_ForwardIterator1 __find_end_classic(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate& __pred) {
@@ -208,7 +208,7 @@ _ForwardIterator1 __find_end_classic(_ForwardIterator1 __first1, _ForwardIterato
}
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate __pred) {
@@ -216,12 +216,10 @@ _ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1
}
template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator1 find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2) {
- using __v1 = typename iterator_traits<_ForwardIterator1>::value_type;
- using __v2 = typename iterator_traits<_ForwardIterator2>::value_type;
- return std::find_end(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+ return std::find_end(__first1, __last1, __first2, __last2, __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h
index b968329fc318..12f0109a616c 100644
--- a/libcxx/include/__algorithm/find_first_of.h
+++ b/libcxx/include/__algorithm/find_first_of.h
@@ -21,10 +21,12 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator1 __find_first_of_ce(_ForwardIterator1 __first1,
+_LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
- _ForwardIterator2 __last2, _BinaryPredicate __pred) {
+ _ForwardIterator2 __last2,
+ _BinaryPredicate&& __pred) {
for (; __first1 != __last1; ++__first1)
for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
if (__pred(*__first1, *__j))
@@ -33,18 +35,16 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator1 __find_first_of_ce(_ForwardItera
}
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
find_first_of(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
_ForwardIterator2 __last2, _BinaryPredicate __pred) {
return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred);
}
template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator1 find_first_of(
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of(
_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
- typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
- typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
- return _VSTD::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+ return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/find_if.h b/libcxx/include/__algorithm/find_if.h
index aa98171a1f61..f4ef3ac31cfe 100644
--- a/libcxx/include/__algorithm/find_if.h
+++ b/libcxx/include/__algorithm/find_if.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (__pred(*__first))
diff --git a/libcxx/include/__algorithm/find_if_not.h b/libcxx/include/__algorithm/find_if_not.h
index 61ddab0b9805..96c159cf5ed3 100644
--- a/libcxx/include/__algorithm/find_if_not.h
+++ b/libcxx/include/__algorithm/find_if_not.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (!__pred(*__first))
diff --git a/libcxx/include/__algorithm/for_each.h b/libcxx/include/__algorithm/for_each.h
index bfbd37c3a3a4..6564f31cd0e7 100644
--- a/libcxx/include/__algorithm/for_each.h
+++ b/libcxx/include/__algorithm/for_each.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Function>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Function for_each(_InputIterator __first,
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function for_each(_InputIterator __first,
_InputIterator __last,
_Function __f) {
for (; __first != __last; ++__first)
diff --git a/libcxx/include/__algorithm/for_each_n.h b/libcxx/include/__algorithm/for_each_n.h
index 2552b40c2781..38d204a11819 100644
--- a/libcxx/include/__algorithm/for_each_n.h
+++ b/libcxx/include/__algorithm/for_each_n.h
@@ -11,6 +11,7 @@
#define _LIBCPP___ALGORITHM_FOR_EACH_N_H
#include <__config>
+#include <__utility/convert_to_integral.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -22,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 14
template <class _InputIterator, class _Size, class _Function>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _InputIterator for_each_n(_InputIterator __first,
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator for_each_n(_InputIterator __first,
_Size __orig_n,
_Function __f) {
typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize;
diff --git a/libcxx/include/__algorithm/generate.h b/libcxx/include/__algorithm/generate.h
index dacbd8c68195..48e21b51e6c4 100644
--- a/libcxx/include/__algorithm/generate.h
+++ b/libcxx/include/__algorithm/generate.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Generator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
generate(_ForwardIterator __first, _ForwardIterator __last, _Generator __gen)
{
diff --git a/libcxx/include/__algorithm/generate_n.h b/libcxx/include/__algorithm/generate_n.h
index 2650e9e5d8b7..45259989bf0e 100644
--- a/libcxx/include/__algorithm/generate_n.h
+++ b/libcxx/include/__algorithm/generate_n.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_GENERATE_N_H
#include <__config>
+#include <__utility/convert_to_integral.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -19,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _OutputIterator, class _Size, class _Generator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen)
{
diff --git a/libcxx/include/__algorithm/half_positive.h b/libcxx/include/__algorithm/half_positive.h
index 7666ef1449c6..74aede2b5668 100644
--- a/libcxx/include/__algorithm/half_positive.h
+++ b/libcxx/include/__algorithm/half_positive.h
@@ -29,7 +29,7 @@ typename enable_if
>::type
__half_positive(_Integral __value)
{
- return static_cast<_Integral>(static_cast<typename make_unsigned<_Integral>::type>(__value) / 2);
+ return static_cast<_Integral>(static_cast<__make_unsigned_t<_Integral> >(__value) / 2);
}
template <typename _Tp>
diff --git a/libcxx/include/__algorithm/in_found_result.h b/libcxx/include/__algorithm/in_found_result.h
index d43f45cd80ef..3134d6e0df2c 100644
--- a/libcxx/include/__algorithm/in_found_result.h
+++ b/libcxx/include/__algorithm/in_found_result.h
@@ -18,7 +18,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -44,6 +44,6 @@ struct in_found_result {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_IN_FOUND_RESULT_H
diff --git a/libcxx/include/__algorithm/in_fun_result.h b/libcxx/include/__algorithm/in_fun_result.h
index 21efa655063d..3cbb9e12d3b3 100644
--- a/libcxx/include/__algorithm/in_fun_result.h
+++ b/libcxx/include/__algorithm/in_fun_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
template <class _InIter1, class _Func1>
@@ -42,7 +42,7 @@ struct in_fun_result {
};
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_in_out_result.h b/libcxx/include/__algorithm/in_in_out_result.h
index e45fef187e0d..3e747be44d66 100644
--- a/libcxx/include/__algorithm/in_in_out_result.h
+++ b/libcxx/include/__algorithm/in_in_out_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -49,7 +49,7 @@ struct in_in_out_result {
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_in_result.h b/libcxx/include/__algorithm/in_in_result.h
index 39e64ced33b2..2098c188cc9f 100644
--- a/libcxx/include/__algorithm/in_in_result.h
+++ b/libcxx/include/__algorithm/in_in_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -46,7 +46,7 @@ struct in_in_result {
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_out_out_result.h b/libcxx/include/__algorithm/in_out_out_result.h
index 52a883b17627..4046eee57df1 100644
--- a/libcxx/include/__algorithm/in_out_out_result.h
+++ b/libcxx/include/__algorithm/in_out_out_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
template <class _InIter1, class _OutIter1, class _OutIter2>
@@ -47,7 +47,7 @@ struct in_out_out_result {
};
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/in_out_result.h b/libcxx/include/__algorithm/in_out_result.h
index 47e6f3907943..7f5a0271b4c1 100644
--- a/libcxx/include/__algorithm/in_out_result.h
+++ b/libcxx/include/__algorithm/in_out_result.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -46,7 +46,7 @@ struct in_out_result {
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h
index c64194a2c826..cc39f275bf44 100644
--- a/libcxx/include/__algorithm/includes.h
+++ b/libcxx/include/__algorithm/includes.h
@@ -25,7 +25,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Comp, class _Proj1, class _Proj2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
_Comp&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) {
for (; __first2 != __last2; ++__first1) {
@@ -39,7 +39,7 @@ __includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
}
template <class _InputIterator1, class _InputIterator2, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool includes(
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool includes(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
@@ -48,14 +48,18 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
static_assert(__is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value,
"Comparator has to be callable");
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
return std::__includes(
- std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
- static_cast<_Comp_ref>(__comp), __identity(), __identity());
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ static_cast<__comp_ref_type<_Compare> >(__comp),
+ __identity(),
+ __identity());
}
template <class _InputIterator1, class _InputIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
includes(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
return std::includes(
std::move(__first1),
diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h
index cb662e791872..5bbefc94bdf2 100644
--- a/libcxx/include/__algorithm/inplace_merge.h
+++ b/libcxx/include/__algorithm/inplace_merge.h
@@ -23,7 +23,11 @@
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/reverse_iterator.h>
-#include <memory>
+#include <__memory/destruct_n.h>
+#include <__memory/temporary_buffer.h>
+#include <__memory/unique_ptr.h>
+#include <__utility/pair.h>
+#include <new>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -54,18 +58,18 @@ public:
bool operator()(const _T1& __x, const _T2& __y) {return __p_(__y, __x);}
};
-template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2,
- class _OutputIterator>
-void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1,
- _InputIterator2 __first2, _InputIterator2 __last2,
- _OutputIterator __result, _Compare __comp)
+template <class _AlgPolicy, class _Compare, class _InputIterator1, class _Sent1,
+ class _InputIterator2, class _Sent2, class _OutputIterator>
+_LIBCPP_HIDE_FROM_ABI
+void __half_inplace_merge(_InputIterator1 __first1, _Sent1 __last1,
+ _InputIterator2 __first2, _Sent2 __last2,
+ _OutputIterator __result, _Compare&& __comp)
{
for (; __first1 != __last1; ++__result)
{
if (__first2 == __last2)
{
- // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `move`.
- _VSTD::move(__first1, __last1, __result);
+ std::__move<_AlgPolicy>(__first1, __last1, __result);
return;
}
@@ -84,13 +88,16 @@ void __half_inplace_merge(_InputIterator1 __first1, _InputIterator1 __last1,
}
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
-void
-__buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
- _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
- typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
- typename iterator_traits<_BidirectionalIterator>::value_type* __buff)
-{
- typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
+_LIBCPP_HIDE_FROM_ABI
+void __buffered_inplace_merge(
+ _BidirectionalIterator __first,
+ _BidirectionalIterator __middle,
+ _BidirectionalIterator __last,
+ _Compare&& __comp,
+ typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
+ typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
+ typename iterator_traits<_BidirectionalIterator>::value_type* __buff) {
+ typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h2(__buff, __d);
if (__len1 <= __len2)
@@ -98,7 +105,7 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator
value_type* __p = __buff;
for (_BidirectionalIterator __i = __first; __i != __middle; __d.template __incr<value_type>(), (void) ++__i, (void) ++__p)
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
- std::__half_inplace_merge<_AlgPolicy, _Compare>(__buff, __p, __middle, __last, __first, __comp);
+ std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp);
}
else
{
@@ -108,19 +115,22 @@ __buffered_inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator
typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi;
typedef __unconstrained_reverse_iterator<value_type*> _Rv;
typedef __invert<_Compare> _Inverted;
- std::__half_inplace_merge<_AlgPolicy, _Inverted>(_Rv(__p), _Rv(__buff),
+ std::__half_inplace_merge<_AlgPolicy>(_Rv(__p), _Rv(__buff),
_RBi(__middle), _RBi(__first),
_RBi(__last), _Inverted(__comp));
}
}
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
-void
-__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
- _Compare __comp, typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
- typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
- typename iterator_traits<_BidirectionalIterator>::value_type* __buff, ptrdiff_t __buff_size)
-{
+void __inplace_merge(
+ _BidirectionalIterator __first,
+ _BidirectionalIterator __middle,
+ _BidirectionalIterator __last,
+ _Compare&& __comp,
+ typename iterator_traits<_BidirectionalIterator>::difference_type __len1,
+ typename iterator_traits<_BidirectionalIterator>::difference_type __len2,
+ typename iterator_traits<_BidirectionalIterator>::value_type* __buff,
+ ptrdiff_t __buff_size) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
@@ -130,7 +140,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
if (__len2 == 0)
return;
if (__len1 <= __buff_size || __len2 <= __buff_size)
- return std::__buffered_inplace_merge<_AlgPolicy, _Compare>
+ return std::__buffered_inplace_merge<_AlgPolicy>
(__first, __middle, __last, __comp, __len1, __len2, __buff);
// shrink [__first, __middle) as much as possible (with no moves), returning if it shrinks to 0
for (; true; ++__first, (void) --__len1)
@@ -158,8 +168,7 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
__len21 = __len2 / 2;
__m2 = __middle;
_Ops::advance(__m2, __len21);
- // TODO: replace _ClassicAlgPolicy and __identity with _AlgPolicy and projection
- __m1 = std::__upper_bound<_ClassicAlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
+ __m1 = std::__upper_bound<_AlgPolicy>(__first, __middle, *__m2, __comp, std::__identity());
__len11 = _Ops::distance(__first, __m1);
}
else
@@ -181,15 +190,13 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
difference_type __len22 = __len2 - __len21; // distance(__m2, __last)
// [__first, __m1) [__m1, __middle) [__middle, __m2) [__m2, __last)
// swap middle two partitions
- // TODO(alg-policy): pass `_AlgPolicy` once it's supported by `rotate`.
- __middle = _VSTD::rotate(__m1, __middle, __m2);
+ __middle = std::__rotate<_AlgPolicy>(__m1, __middle, __m2).first;
// __len12 and __len21 now have swapped meanings
// merge smaller range with recursive call and larger with tail recursion elimination
if (__len11 + __len21 < __len12 + __len22)
{
- std::__inplace_merge<_AlgPolicy, _Compare>(
+ std::__inplace_merge<_AlgPolicy>(
__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
-// _VSTD::__inplace_merge<_Compare>(__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
__first = __middle;
__middle = __m2;
__len1 = __len12;
@@ -197,9 +204,8 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
}
else
{
- std::__inplace_merge<_AlgPolicy, _Compare>(
+ std::__inplace_merge<_AlgPolicy>(
__middle, __m2, __last, __comp, __len12, __len22, __buff, __buff_size);
-// _VSTD::__inplace_merge<_Compare>(__first, __m1, __middle, __comp, __len11, __len21, __buff, __buff_size);
__last = __middle;
__middle = __m1;
__len1 = __len11;
@@ -208,33 +214,39 @@ __inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle,
}
}
-template <class _BidirectionalIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY
+template <class _AlgPolicy, class _BidirectionalIterator, class _Compare>
+_LIBCPP_HIDE_FROM_ABI
void
-inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
- _Compare __comp)
+__inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
+ _Compare&& __comp)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
- difference_type __len1 = _VSTD::distance(__first, __middle);
- difference_type __len2 = _VSTD::distance(__middle, __last);
+ difference_type __len1 = _IterOps<_AlgPolicy>::distance(__first, __middle);
+ difference_type __len2 = _IterOps<_AlgPolicy>::distance(__middle, __last);
difference_type __buf_size = _VSTD::min(__len1, __len2);
// TODO: Remove the use of std::get_temporary_buffer
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
pair<value_type*, ptrdiff_t> __buf = _VSTD::get_temporary_buffer<value_type>(__buf_size);
_LIBCPP_SUPPRESS_DEPRECATED_POP
unique_ptr<value_type, __return_temporary_buffer> __h(__buf.first);
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__inplace_merge<_ClassicAlgPolicy, _Comp_ref>(__first, __middle, __last, __comp, __len1, __len2,
- __buf.first, __buf.second);
+ return std::__inplace_merge<_AlgPolicy>(
+ std::move(__first), std::move(__middle), std::move(__last), __comp, __len1, __len2, __buf.first, __buf.second);
+}
+
+template <class _BidirectionalIterator, class _Compare>
+inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(
+ _BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) {
+ std::__inplace_merge<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp));
}
template <class _BidirectionalIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_HIDE_FROM_ABI
void
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last)
{
- _VSTD::inplace_merge(__first, __middle, __last,
+ std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last),
__less<typename iterator_traits<_BidirectionalIterator>::value_type>());
}
diff --git a/libcxx/include/__algorithm/is_heap.h b/libcxx/include/__algorithm/is_heap.h
index 0d399a09b857..2dcb4a28e8d7 100644
--- a/libcxx/include/__algorithm/is_heap.h
+++ b/libcxx/include/__algorithm/is_heap.h
@@ -23,17 +23,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _RandomAccessIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__is_heap_until(__first, __last, static_cast<_Comp_ref>(__comp)) == __last;
+ return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp)) == __last;
}
template<class _RandomAccessIterator>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
diff --git a/libcxx/include/__algorithm/is_heap_until.h b/libcxx/include/__algorithm/is_heap_until.h
index adb35af887fb..6ed4cb29c423 100644
--- a/libcxx/include/__algorithm/is_heap_until.h
+++ b/libcxx/include/__algorithm/is_heap_until.h
@@ -21,7 +21,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _RandomAccessIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
__is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -48,15 +48,14 @@ __is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co
}
template <class _RandomAccessIterator, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__is_heap_until(__first, __last, static_cast<_Comp_ref>(__comp));
+ return std::__is_heap_until(__first, __last, static_cast<__comp_ref_type<_Compare> >(__comp));
}
template<class _RandomAccessIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
return _VSTD::__is_heap_until(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/is_partitioned.h b/libcxx/include/__algorithm/is_partitioned.h
index b4f421cfc053..ab59d3cce582 100644
--- a/libcxx/include/__algorithm/is_partitioned.h
+++ b/libcxx/include/__algorithm/is_partitioned.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
is_partitioned(_InputIterator __first, _InputIterator __last, _Predicate __pred)
{
for (; __first != __last; ++__first)
diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index cdd742048412..005445652e9d 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -11,10 +11,16 @@
#define _LIBCPP___ALGORITHM_IS_PERMUTATION_H
#include <__algorithm/comp.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
+#include <__functional/identity.h>
+#include <__functional/invoke.h>
+#include <__iterator/concepts.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
+#include <__utility/move.h>
+#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -22,140 +28,210 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
-is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
- _BinaryPredicate __pred) {
- // shorten sequences as much as possible by lopping of any equal prefix
- for (; __first1 != __last1; ++__first1, (void)++__first2)
- if (!__pred(*__first1, *__first2))
- break;
- if (__first1 == __last1)
- return true;
+template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class = void>
+struct _ConstTimeDistance : false_type {};
- // __first1 != __last1 && *__first1 != *__first2
- typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1;
- _D1 __l1 = _VSTD::distance(__first1, __last1);
- if (__l1 == _D1(1))
- return false;
- _ForwardIterator2 __last2 = _VSTD::next(__first2, __l1);
- // For each element in [f1, l1) see if there are the same number of
- // equal elements in [f2, l2)
- for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) {
+#if _LIBCPP_STD_VER > 17
+
+template <class _Iter1, class _Sent1, class _Iter2, class _Sent2>
+struct _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2, __enable_if_t<
+ sized_sentinel_for<_Sent1, _Iter1> &&
+ sized_sentinel_for<_Sent2, _Iter2>
+>> : true_type {};
+
+#else
+
+template <class _Iter1, class _Iter2>
+struct _ConstTimeDistance<_Iter1, _Iter1, _Iter2, _Iter2, __enable_if_t<
+ is_same<typename iterator_traits<_Iter1>::iterator_category, random_access_iterator_tag>::value &&
+ is_same<typename iterator_traits<_Iter2>::iterator_category, random_access_iterator_tag>::value
+> > : true_type {};
+
+#endif // _LIBCPP_STD_VER > 17
+
+// Internal functions
+
+// For each element in [f1, l1) see if there are the same number of equal elements in [f2, l2)
+template <class _AlgPolicy,
+ class _Iter1, class _Sent1, class _Iter2, class _Sent2,
+ class _Proj1, class _Proj2, class _Pred>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+__is_permutation_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
+ using _D1 = __iter_diff_t<_Iter1>;
+
+ for (auto __i = __first1; __i != __last1; ++__i) {
// Have we already counted the number of *__i in [f1, l1)?
- _ForwardIterator1 __match = __first1;
- for (; __match != __i; ++__match)
- if (__pred(*__match, *__i))
+ auto __match = __first1;
+ for (; __match != __i; ++__match) {
+ if (std::__invoke(__pred, std::__invoke(__proj1, *__match), std::__invoke(__proj1, *__i)))
break;
+ }
+
if (__match == __i) {
// Count number of *__i in [f2, l2)
_D1 __c2 = 0;
- for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
- if (__pred(*__i, *__j))
+ for (auto __j = __first2; __j != __last2; ++__j) {
+ if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj2, *__j)))
++__c2;
+ }
if (__c2 == 0)
return false;
+
// Count number of *__i in [__i, l1) (we can start with 1)
_D1 __c1 = 1;
- for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j)
- if (__pred(*__i, *__j))
+ for (auto __j = _IterOps<_AlgPolicy>::next(__i); __j != __last1; ++__j) {
+ if (std::__invoke(__pred, std::__invoke(__proj1, *__i), std::__invoke(__proj1, *__j)))
++__c1;
+ }
if (__c1 != __c2)
return false;
}
}
+
return true;
}
-template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
-is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
- typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
- typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
- return _VSTD::is_permutation(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+// 2+1 iterators, predicate. Not used by range algorithms.
+template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _BinaryPredicate>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+__is_permutation(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2,
+ _BinaryPredicate&& __pred) {
+ // Shorten sequences as much as possible by lopping of any equal prefix.
+ for (; __first1 != __last1; ++__first1, (void)++__first2) {
+ if (!__pred(*__first1, *__first2))
+ break;
+ }
+
+ if (__first1 == __last1)
+ return true;
+
+ // __first1 != __last1 && *__first1 != *__first2
+ using _D1 = __iter_diff_t<_ForwardIterator1>;
+ _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
+ if (__l1 == _D1(1))
+ return false;
+ auto __last2 = _IterOps<_AlgPolicy>::next(__first2, __l1);
+
+ return std::__is_permutation_impl<_AlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __identity(), __identity());
}
-#if _LIBCPP_STD_VER > 11
-template <class _BinaryPredicate, class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
-__is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
- _ForwardIterator2 __last2, _BinaryPredicate __pred, forward_iterator_tag, forward_iterator_tag) {
- // shorten sequences as much as possible by lopping of any equal prefix
- for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
- if (!__pred(*__first1, *__first2))
+// 2+2 iterators, predicate, non-constant time `distance`.
+template <class _AlgPolicy,
+ class _Iter1, class _Sent1, class _Iter2, class _Sent2,
+ class _Proj1, class _Proj2, class _Pred>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2,
+ /*_ConstTimeDistance=*/false_type) {
+ // Shorten sequences as much as possible by lopping of any equal prefix.
+ while (__first1 != __last1 && __first2 != __last2) {
+ if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
break;
+ ++__first1;
+ ++__first2;
+ }
+
if (__first1 == __last1)
return __first2 == __last2;
- else if (__first2 == __last2)
+ if (__first2 == __last2) // Second range is shorter
return false;
- typedef typename iterator_traits<_ForwardIterator1>::difference_type _D1;
- _D1 __l1 = _VSTD::distance(__first1, __last1);
+ using _D1 = __iter_diff_t<_Iter1>;
+ _D1 __l1 = _IterOps<_AlgPolicy>::distance(__first1, __last1);
- typedef typename iterator_traits<_ForwardIterator2>::difference_type _D2;
- _D2 __l2 = _VSTD::distance(__first2, __last2);
+ using _D2 = __iter_diff_t<_Iter2>;
+ _D2 __l2 = _IterOps<_AlgPolicy>::distance(__first2, __last2);
if (__l1 != __l2)
return false;
- // For each element in [f1, l1) see if there are the same number of
- // equal elements in [f2, l2)
- for (_ForwardIterator1 __i = __first1; __i != __last1; ++__i) {
- // Have we already counted the number of *__i in [f1, l1)?
- _ForwardIterator1 __match = __first1;
- for (; __match != __i; ++__match)
- if (__pred(*__match, *__i))
- break;
- if (__match == __i) {
- // Count number of *__i in [f2, l2)
- _D1 __c2 = 0;
- for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
- if (__pred(*__i, *__j))
- ++__c2;
- if (__c2 == 0)
- return false;
- // Count number of *__i in [__i, l1) (we can start with 1)
- _D1 __c1 = 1;
- for (_ForwardIterator1 __j = _VSTD::next(__i); __j != __last1; ++__j)
- if (__pred(*__i, *__j))
- ++__c1;
- if (__c1 != __c2)
- return false;
- }
- }
- return true;
+ return std::__is_permutation_impl<_AlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __proj1, __proj2);
}
-template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 bool __is_permutation(_RandomAccessIterator1 __first1, _RandomAccessIterator2 __last1,
- _RandomAccessIterator1 __first2, _RandomAccessIterator2 __last2,
- _BinaryPredicate __pred, random_access_iterator_tag,
- random_access_iterator_tag) {
- if (_VSTD::distance(__first1, __last1) != _VSTD::distance(__first2, __last2))
+// 2+2 iterators, predicate, specialization for constant-time `distance` call.
+template <class _AlgPolicy,
+ class _Iter1, class _Sent1, class _Iter2, class _Sent2,
+ class _Proj1, class _Proj2, class _Pred>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2,
+ /*_ConstTimeDistance=*/true_type) {
+ if (std::distance(__first1, __last1) != std::distance(__first2, __last2))
return false;
- return _VSTD::is_permutation<_RandomAccessIterator1, _RandomAccessIterator2,
- _BinaryPredicate&>(__first1, __last1, __first2, __pred);
+ return std::__is_permutation<_AlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __proj1, __proj2,
+ /*_ConstTimeDistance=*/false_type());
+}
+
+// 2+2 iterators, predicate
+template <class _AlgPolicy,
+ class _Iter1, class _Sent1, class _Iter2, class _Sent2,
+ class _Proj1, class _Proj2, class _Pred>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+__is_permutation(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
+ return std::__is_permutation<_AlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __proj1, __proj2,
+ _ConstTimeDistance<_Iter1, _Sent1, _Iter2, _Sent2>());
}
+// Public interface
+
+// 2+1 iterators, predicate
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
- _ForwardIterator2 __last2, _BinaryPredicate __pred) {
- return _VSTD::__is_permutation<_BinaryPredicate&>(
- __first1, __last1, __first2, __last2, __pred, typename iterator_traits<_ForwardIterator1>::iterator_category(),
- typename iterator_traits<_ForwardIterator2>::iterator_category());
+ _BinaryPredicate __pred) {
+ static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
+ "The predicate has to be callable");
+
+ return std::__is_permutation<_ClassicAlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), __pred);
+}
+
+// 2+1 iterators
+template <class _ForwardIterator1, class _ForwardIterator2>
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
+is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
+ return std::is_permutation(__first1, __last1, __first2, __equal_to());
}
+#if _LIBCPP_STD_VER > 11
+
+// 2+2 iterators
template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool is_permutation(
+ _ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
+ return std::__is_permutation<_ClassicAlgPolicy>(
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ __equal_to(),
+ __identity(),
+ __identity());
+}
+
+// 2+2 iterators, predicate
+template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
- _ForwardIterator2 __last2) {
- typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
- typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
- return _VSTD::__is_permutation(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>(),
- typename iterator_traits<_ForwardIterator1>::iterator_category(),
- typename iterator_traits<_ForwardIterator2>::iterator_category());
+ _ForwardIterator2 __last2, _BinaryPredicate __pred) {
+ static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
+ "The predicate has to be callable");
+
+ return std::__is_permutation<_ClassicAlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __identity(), __identity());
}
-#endif
+
+#endif // _LIBCPP_STD_VER > 11
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/is_sorted.h b/libcxx/include/__algorithm/is_sorted.h
index 56de95bb31b7..bf44f45764d5 100644
--- a/libcxx/include/__algorithm/is_sorted.h
+++ b/libcxx/include/__algorithm/is_sorted.h
@@ -23,17 +23,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
is_sorted(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__is_sorted_until<_Comp_ref>(__first, __last, __comp) == __last;
+ return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp) == __last;
}
template<class _ForwardIterator>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
is_sorted(_ForwardIterator __first, _ForwardIterator __last)
{
diff --git a/libcxx/include/__algorithm/is_sorted_until.h b/libcxx/include/__algorithm/is_sorted_until.h
index 338d28508c17..b6683000a069 100644
--- a/libcxx/include/__algorithm/is_sorted_until.h
+++ b/libcxx/include/__algorithm/is_sorted_until.h
@@ -21,7 +21,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _ForwardIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
__is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
if (__first != __last)
@@ -38,15 +38,14 @@ __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __
}
template <class _ForwardIterator, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__is_sorted_until<_Comp_ref>(__first, __last, __comp);
+ return _VSTD::__is_sorted_until<__comp_ref_type<_Compare> >(__first, __last, __comp);
}
template<class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
is_sorted_until(_ForwardIterator __first, _ForwardIterator __last)
{
return _VSTD::is_sorted_until(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/iter_swap.h b/libcxx/include/__algorithm/iter_swap.h
index 038859e1361d..44422b5de0f0 100644
--- a/libcxx/include/__algorithm/iter_swap.h
+++ b/libcxx/include/__algorithm/iter_swap.h
@@ -20,10 +20,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator1, class _ForwardIterator2>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void iter_swap(_ForwardIterator1 __a,
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 void iter_swap(_ForwardIterator1 __a,
_ForwardIterator2 __b)
// _NOEXCEPT_(_NOEXCEPT_(swap(*__a, *__b)))
- _NOEXCEPT_(_NOEXCEPT_(swap(*declval<_ForwardIterator1>(), *declval<_ForwardIterator2>()))) {
+ _NOEXCEPT_(_NOEXCEPT_(swap(*std::declval<_ForwardIterator1>(), *std::declval<_ForwardIterator2>()))) {
swap(*__a, *__b);
}
diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h
index 8307d71214e5..bd3e6f1d38fd 100644
--- a/libcxx/include/__algorithm/iterator_operations.h
+++ b/libcxx/include/__algorithm/iterator_operations.h
@@ -10,16 +10,24 @@
#define _LIBCPP___ALGORITHM_ITERATOR_OPERATIONS_H
#include <__algorithm/iter_swap.h>
+#include <__algorithm/ranges_iterator_concept.h>
#include <__config>
#include <__iterator/advance.h>
#include <__iterator/distance.h>
+#include <__iterator/incrementable_traits.h>
#include <__iterator/iter_move.h>
#include <__iterator/iter_swap.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/next.h>
+#include <__iterator/prev.h>
+#include <__iterator/readable_traits.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_reference.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/move.h>
-#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -29,16 +37,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy> struct _IterOps;
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
struct _RangeAlgPolicy {};
template <>
struct _IterOps<_RangeAlgPolicy> {
+
+ template <class _Iter>
+ using __value_type = iter_value_t<_Iter>;
+
+ template <class _Iter>
+ using __iterator_category = ranges::__iterator_concept<_Iter>;
+
+ template <class _Iter>
+ using __difference_type = iter_difference_t<_Iter>;
+
static constexpr auto advance = ranges::advance;
static constexpr auto distance = ranges::distance;
static constexpr auto __iter_move = ranges::iter_move;
static constexpr auto iter_swap = ranges::iter_swap;
static constexpr auto next = ranges::next;
+ static constexpr auto prev = ranges::prev;
static constexpr auto __advance_to = ranges::advance;
};
@@ -49,64 +68,103 @@ struct _ClassicAlgPolicy {};
template <>
struct _IterOps<_ClassicAlgPolicy> {
+ template <class _Iter>
+ using __value_type = typename iterator_traits<_Iter>::value_type;
+
+ template <class _Iter>
+ using __iterator_category = typename iterator_traits<_Iter>::iterator_category;
+
+ template <class _Iter>
+ using __difference_type = typename iterator_traits<_Iter>::difference_type;
+
// advance
template <class _Iter, class _Distance>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
static void advance(_Iter& __iter, _Distance __count) {
std::advance(__iter, __count);
}
// distance
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
static typename iterator_traits<_Iter>::difference_type distance(_Iter __first, _Iter __last) {
return std::distance(__first, __last);
}
+ template <class _Iter>
+ using __deref_t = decltype(*std::declval<_Iter&>());
+
+ template <class _Iter>
+ using __move_t = decltype(std::move(*std::declval<_Iter&>()));
+
+ template <class _Iter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+ static void __validate_iter_reference() {
+ static_assert(is_same<__deref_t<_Iter>, typename iterator_traits<__remove_cvref_t<_Iter> >::reference>::value,
+ "It looks like your iterator's `iterator_traits<It>::reference` does not match the return type of "
+ "dereferencing the iterator, i.e., calling `*it`. This is undefined behavior according to [input.iterators] "
+ "and can lead to dangling reference issues at runtime, so we are flagging this.");
+ }
+
// iter_move
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
- // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce.
- static __enable_if_t<
- is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value,
- typename remove_reference< typename iterator_traits<__uncvref_t<_Iter> >::reference >::type&&>
- __iter_move(_Iter&& __i) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
+ // If the result of dereferencing `_Iter` is a reference type, deduce the result of calling `std::move` on it. Note
+ // that the C++03 mode doesn't support `decltype(auto)` as the return type.
+ __enable_if_t<
+ is_reference<__deref_t<_Iter> >::value,
+ __move_t<_Iter> >
+ __iter_move(_Iter&& __i) {
+ __validate_iter_reference<_Iter>();
+
return std::move(*std::forward<_Iter>(__i));
}
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
- // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce.
- static __enable_if_t<
- !is_reference<typename iterator_traits<__uncvref_t<_Iter> >::reference>::value,
- typename iterator_traits<__uncvref_t<_Iter> >::reference>
- __iter_move(_Iter&& __i) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
+ // If the result of dereferencing `_Iter` is a value type, deduce the return value of this function to also be a
+ // value -- otherwise, after `operator*` returns a temporary, this function would return a dangling reference to that
+ // temporary. Note that the C++03 mode doesn't support `auto` as the return type.
+ __enable_if_t<
+ !is_reference<__deref_t<_Iter> >::value,
+ __deref_t<_Iter> >
+ __iter_move(_Iter&& __i) {
+ __validate_iter_reference<_Iter>();
+
return *std::forward<_Iter>(__i);
}
// iter_swap
template <class _Iter1, class _Iter2>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
static void iter_swap(_Iter1&& __a, _Iter2&& __b) {
std::iter_swap(std::forward<_Iter1>(__a), std::forward<_Iter2>(__b));
}
// next
template <class _Iterator>
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
_Iterator next(_Iterator, _Iterator __last) {
return __last;
}
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
- __uncvref_t<_Iter> next(_Iter&& __it,
- typename iterator_traits<__uncvref_t<_Iter> >::difference_type __n = 1){
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
+ __remove_cvref_t<_Iter> next(_Iter&& __it,
+ typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
return std::next(std::forward<_Iter>(__it), __n);
}
+ // prev
+ template <class _Iter>
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
+ __remove_cvref_t<_Iter> prev(_Iter&& __iter,
+ typename iterator_traits<__remove_cvref_t<_Iter> >::difference_type __n = 1) {
+ return std::prev(std::forward<_Iter>(__iter), __n);
+ }
+
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX14
void __advance_to(_Iter& __first, _Iter __last) {
__first = __last;
}
diff --git a/libcxx/include/__algorithm/lexicographical_compare.h b/libcxx/include/__algorithm/lexicographical_compare.h
index 30ddf2408120..0a13c5dd31c8 100644
--- a/libcxx/include/__algorithm/lexicographical_compare.h
+++ b/libcxx/include/__algorithm/lexicographical_compare.h
@@ -21,7 +21,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _InputIterator1, class _InputIterator2>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
__lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp)
{
@@ -37,18 +37,17 @@ __lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1,
template <class _InputIterator1, class _InputIterator2, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__lexicographical_compare<_Comp_ref>(__first1, __last1, __first2, __last2, __comp);
+ return _VSTD::__lexicographical_compare<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __comp);
}
template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
lexicographical_compare(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2)
diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index 2c92f715265a..2648982ea506 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -29,7 +29,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Iter, class _Sent, class _Type, class _Proj, class _Comp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_Iter __lower_bound_impl(_Iter __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
auto __len = _IterOps<_AlgPolicy>::distance(__first, __last);
@@ -48,7 +48,7 @@ _Iter __lower_bound_impl(_Iter __first, _Sent __last, const _Type& __value, _Com
}
template <class _ForwardIterator, class _Tp, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
static_assert(__is_callable<_Compare, decltype(*__first), const _Tp&>::value,
"The comparator has to be callable");
@@ -57,7 +57,7 @@ _ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last,
}
template <class _ForwardIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
return std::lower_bound(__first, __last, __value,
__less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>());
diff --git a/libcxx/include/__algorithm/make_heap.h b/libcxx/include/__algorithm/make_heap.h
index bf9dd96756af..d66cfe2e5fc9 100644
--- a/libcxx/include/__algorithm/make_heap.h
+++ b/libcxx/include/__algorithm/make_heap.h
@@ -24,29 +24,28 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
- using _CompRef = typename __comp_ref_type<_Compare>::type;
- _CompRef __comp_ref = __comp;
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+void __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
+ __comp_ref_type<_Compare> __comp_ref = __comp;
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
difference_type __n = __last - __first;
if (__n > 1) {
// start from the first parent, there is no need to consider children
for (difference_type __start = (__n - 2) / 2; __start >= 0; --__start) {
- std::__sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __n, __first + __start);
+ std::__sift_down<_AlgPolicy>(__first, __comp_ref, __n, __first + __start);
}
}
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
std::__make_heap<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::make_heap(std::move(__first), std::move(__last),
__less<typename iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/make_projected.h b/libcxx/include/__algorithm/make_projected.h
index 64fc3dfb6a12..87d4d59042c6 100644
--- a/libcxx/include/__algorithm/make_projected.h
+++ b/libcxx/include/__algorithm/make_projected.h
@@ -14,51 +14,91 @@
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__type_traits/decay.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/integral_constant.h>
#include <__type_traits/is_member_pointer.h>
+#include <__type_traits/is_same.h>
+#include <__utility/declval.h>
#include <__utility/forward.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
-
_LIBCPP_BEGIN_NAMESPACE_STD
-namespace ranges {
-
template <class _Pred, class _Proj>
-_LIBCPP_HIDE_FROM_ABI constexpr static
-decltype(auto) __make_projected_pred(_Pred& __pred, _Proj& __proj) {
- if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Pred>>) {
- // Avoid creating the lambda and just use the pristine predicate -- for certain algorithms, this would enable
- // optimizations that rely on the type of the predicate.
- return __pred;
+struct _ProjectedPred {
+ _Pred& __pred; // Can be a unary or a binary predicate.
+ _Proj& __proj;
+
+ _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {}
+
+ template <class _Tp>
+ typename __invoke_of<_Pred&,
+ decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))
+ >::type
+ _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const {
+ return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v)));
+ }
- } else {
- return [&](auto&& __x) {
- return std::invoke(__pred, std::invoke(__proj, std::forward<decltype(__x)>(__x)));
- };
+ template <class _T1, class _T2>
+ typename __invoke_of<_Pred&,
+ decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
+ decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))
+ >::type
+ _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const {
+ return std::__invoke(__pred,
+ std::__invoke(__proj, std::forward<_T1>(__lhs)),
+ std::__invoke(__proj, std::forward<_T2>(__rhs)));
}
-}
-template <class _Comp, class _Proj>
-_LIBCPP_HIDE_FROM_ABI constexpr static
-decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) {
- if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Comp>>) {
- // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable
- // optimizations that rely on the type of the comparator.
- return __comp;
+};
- } else {
- return [&](auto&& __lhs, auto&& __rhs) {
- return std::invoke(__comp,
- std::invoke(__proj, std::forward<decltype(__lhs)>(__lhs)),
- std::invoke(__proj, std::forward<decltype(__rhs)>(__rhs)));
- };
- }
+template <class _Pred, class _Proj, class = void>
+struct __can_use_pristine_comp : false_type {};
+
+template <class _Pred, class _Proj>
+struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t<
+ !is_member_pointer<typename decay<_Pred>::type>::value && (
+#if _LIBCPP_STD_VER > 17
+ is_same<typename decay<_Proj>::type, identity>::value ||
+#endif
+ is_same<typename decay<_Proj>::type, __identity>::value
+ )
+> > : true_type {};
+
+template <class _Pred, class _Proj>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static
+__enable_if_t<
+ !__can_use_pristine_comp<_Pred, _Proj>::value,
+ _ProjectedPred<_Pred, _Proj>
+>
+__make_projected(_Pred& __pred, _Proj& __proj) {
+ return _ProjectedPred<_Pred, _Proj>(__pred, __proj);
+}
+
+// Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable
+// optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in
+// the call stack when the comparator is invoked, even in an unoptimized build.
+template <class _Pred, class _Proj>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static
+__enable_if_t<
+ __can_use_pristine_comp<_Pred, _Proj>::value,
+ _Pred&
+>
+__make_projected(_Pred& __pred, _Proj&) {
+ return __pred;
}
+_LIBCPP_END_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+
template <class _Comp, class _Proj1, class _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr static
decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
@@ -81,6 +121,6 @@ decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __p
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H
diff --git a/libcxx/include/__algorithm/max.h b/libcxx/include/__algorithm/max.h
index 345b235a2193..a08a3fc59bda 100644
--- a/libcxx/include/__algorithm/max.h
+++ b/libcxx/include/__algorithm/max.h
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
const _Tp&
max(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
@@ -35,7 +35,7 @@ max(const _Tp& __a, const _Tp& __b, _Compare __comp)
template <class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
const _Tp&
max(const _Tp& __a, const _Tp& __b)
{
@@ -46,17 +46,16 @@ max(const _Tp& __a, const _Tp& __b)
template<class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
_Tp
max(initializer_list<_Tp> __t, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return *_VSTD::__max_element<_Comp_ref>(__t.begin(), __t.end(), __comp);
+ return *_VSTD::__max_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
}
template<class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
_Tp
max(initializer_list<_Tp> __t)
{
diff --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h
index 795ec8e1ddc1..6ac310619bf9 100644
--- a/libcxx/include/__algorithm/max_element.h
+++ b/libcxx/include/__algorithm/max_element.h
@@ -21,7 +21,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _ForwardIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
__max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -37,16 +37,15 @@ __max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp
}
template <class _ForwardIterator, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__max_element<_Comp_ref>(__first, __last, __comp);
+ return _VSTD::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp);
}
template <class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last)
{
return _VSTD::max_element(__first, __last,
diff --git a/libcxx/include/__algorithm/merge.h b/libcxx/include/__algorithm/merge.h
index 48360ed5b445..e54e430bcb6a 100644
--- a/libcxx/include/__algorithm/merge.h
+++ b/libcxx/include/__algorithm/merge.h
@@ -22,7 +22,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
__merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
@@ -46,17 +46,16 @@ __merge(_InputIterator1 __first1, _InputIterator1 __last1,
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__merge<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp);
+ return _VSTD::__merge<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp);
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
merge(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
diff --git a/libcxx/include/__algorithm/min.h b/libcxx/include/__algorithm/min.h
index 3d8c73d78f11..2882485ad76f 100644
--- a/libcxx/include/__algorithm/min.h
+++ b/libcxx/include/__algorithm/min.h
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
const _Tp&
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
@@ -35,7 +35,7 @@ min(const _Tp& __a, const _Tp& __b, _Compare __comp)
template <class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
const _Tp&
min(const _Tp& __a, const _Tp& __b)
{
@@ -46,17 +46,16 @@ min(const _Tp& __a, const _Tp& __b)
template<class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
_Tp
min(initializer_list<_Tp> __t, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return *_VSTD::__min_element<_Comp_ref>(__t.begin(), __t.end(), __comp);
+ return *_VSTD::__min_element<__comp_ref_type<_Compare> >(__t.begin(), __t.end(), __comp);
}
template<class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
_Tp
min(initializer_list<_Tp> __t)
{
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index 17b242c341e6..c0706fe9e44d 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -25,7 +25,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Comp, class _Iter, class _Sent, class _Proj>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
if (__first == __last)
return __first;
@@ -39,14 +39,14 @@ _Iter __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
}
template <class _Comp, class _Iter, class _Sent>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) {
auto __proj = __identity();
return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj);
}
template <class _ForwardIterator, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
{
static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -54,12 +54,11 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value,
"The comparator has to be callable");
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__min_element<_Comp_ref>(std::move(__first), std::move(__last), __comp);
+ return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
}
template <class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
min_element(_ForwardIterator __first, _ForwardIterator __last)
{
return _VSTD::min_element(__first, __last,
diff --git a/libcxx/include/__algorithm/min_max_result.h b/libcxx/include/__algorithm/min_max_result.h
index ca77dcc5725a..4be39992b42c 100644
--- a/libcxx/include/__algorithm/min_max_result.h
+++ b/libcxx/include/__algorithm/min_max_result.h
@@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -47,7 +47,7 @@ struct min_max_result {
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/minmax.h b/libcxx/include/__algorithm/minmax.h
index 7e10b8b8350c..6ef0a777083f 100644
--- a/libcxx/include/__algorithm/minmax.h
+++ b/libcxx/include/__algorithm/minmax.h
@@ -25,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template<class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<const _Tp&, const _Tp&>
minmax(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
@@ -35,7 +35,7 @@ minmax(const _Tp& __a, const _Tp& __b, _Compare __comp)
template<class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<const _Tp&, const _Tp&>
minmax(const _Tp& __a, const _Tp& __b)
{
@@ -45,7 +45,7 @@ minmax(const _Tp& __a, const _Tp& __b)
#ifndef _LIBCPP_CXX03_LANG
template<class _Tp, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) {
static_assert(__is_callable<_Compare, _Tp, _Tp>::value, "The comparator has to be callable");
__identity __proj;
@@ -55,7 +55,7 @@ pair<_Tp, _Tp> minmax(initializer_list<_Tp> __t, _Compare __comp) {
template<class _Tp>
_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Tp, _Tp>
minmax(initializer_list<_Tp> __t)
{
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index cf67184e0b4c..caa963e112e1 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -32,14 +32,14 @@ public:
_MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj) : __comp_(__comp), __proj_(__proj) {}
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool operator()(_Iter& __it1, _Iter& __it2) {
return std::__invoke(__comp_, std::__invoke(__proj_, *__it1), std::__invoke(__proj_, *__it2));
}
};
template <class _Iter, class _Sent, class _Proj, class _Comp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj);
@@ -79,7 +79,7 @@ pair<_Iter, _Iter> __minmax_element_impl(_Iter __first, _Sent __last, _Comp& __c
}
template <class _ForwardIterator, class _Compare>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_ForwardIterator, _ForwardIterator>
minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
static_assert(__is_cpp17_forward_iterator<_ForwardIterator>::value,
@@ -91,7 +91,7 @@ minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __com
}
template <class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_ForwardIterator, _ForwardIterator> minmax_element(_ForwardIterator __first, _ForwardIterator __last) {
return std::minmax_element(__first, __last, __less<typename iterator_traits<_ForwardIterator>::value_type>());
}
diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h
index f2011faf2f9a..600e2cdd3da4 100644
--- a/libcxx/include/__algorithm/mismatch.h
+++ b/libcxx/include/__algorithm/mismatch.h
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) {
for (; __first1 != __last1; ++__first1, (void)++__first2)
if (!__pred(*__first1, *__first2))
@@ -33,17 +33,15 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2) {
- typedef typename iterator_traits<_InputIterator1>::value_type __v1;
- typedef typename iterator_traits<_InputIterator2>::value_type __v2;
- return _VSTD::mismatch(__first1, __last1, __first2, __equal_to<__v1, __v2>());
+ return std::mismatch(__first1, __last1, __first2, __equal_to());
}
#if _LIBCPP_STD_VER > 11
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2,
_BinaryPredicate __pred) {
for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2)
@@ -54,11 +52,9 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
template <class _InputIterator1, class _InputIterator2>
_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_InputIterator1, _InputIterator2>
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2>
mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) {
- typedef typename iterator_traits<_InputIterator1>::value_type __v1;
- typedef typename iterator_traits<_InputIterator2>::value_type __v2;
- return _VSTD::mismatch(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+ return std::mismatch(__first1, __last1, __first2, __last2, __equal_to());
}
#endif
diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h
index 0b08d31c176e..ac95bda7b61f 100644
--- a/libcxx/include/__algorithm/move.h
+++ b/libcxx/include/__algorithm/move.h
@@ -9,107 +9,122 @@
#ifndef _LIBCPP___ALGORITHM_MOVE_H
#define _LIBCPP___ALGORITHM_MOVE_H
-#include <__algorithm/unwrap_iter.h>
+#include <__algorithm/copy_move_common.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/min.h>
#include <__config>
-#include <__iterator/iterator_traits.h>
-#include <__iterator/reverse_iterator.h>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/is_copy_constructible.h>
#include <__utility/move.h>
#include <__utility/pair.h>
-#include <cstring>
-#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-_LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
-// move
+_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _InIter, class _Sent, class _OutIter>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-pair<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
- while (__first != __last) {
- *__result = std::move(*__first);
- ++__first;
- ++__result;
+template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+__move(_InIter __first, _Sent __last, _OutIter __result);
+
+template <class _AlgPolicy>
+struct __move_loop {
+ template <class _InIter, class _Sent, class _OutIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result) const {
+ while (__first != __last) {
+ *__result = _IterOps<_AlgPolicy>::__iter_move(__first);
+ ++__first;
+ ++__result;
+ }
+ return std::make_pair(std::move(__first), std::move(__result));
}
- return std::make_pair(std::move(__first), std::move(__result));
-}
-template <class _InType,
- class _OutType,
- class = __enable_if_t<is_same<typename remove_const<_InType>::type, _OutType>::value
- && is_trivially_move_assignable<_OutType>::value> >
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-pair<_InType*, _OutType*> __move_impl(_InType* __first, _InType* __last, _OutType* __result) {
- if (__libcpp_is_constant_evaluated()
-// TODO: Remove this once GCC supports __builtin_memmove during constant evaluation
-#ifndef _LIBCPP_COMPILER_GCC
- && !is_trivially_copyable<_InType>::value
-#endif
- )
- return std::__move_impl<_InType*, _InType*, _OutType*>(__first, __last, __result);
- const size_t __n = static_cast<size_t>(__last - __first);
- ::__builtin_memmove(__result, __first, __n * sizeof(_OutType));
- return std::make_pair(__first + __n, __result + __n);
-}
-
-template <class>
-struct __is_trivially_move_assignable_unwrapped_impl : false_type {};
-
-template <class _Type>
-struct __is_trivially_move_assignable_unwrapped_impl<_Type*> : is_trivially_move_assignable<_Type> {};
-
-template <class _Iter>
-struct __is_trivially_move_assignable_unwrapped
- : __is_trivially_move_assignable_unwrapped_impl<decltype(std::__unwrap_iter<_Iter>(std::declval<_Iter>()))> {};
-
-template <class _InIter,
- class _OutIter,
- __enable_if_t<is_same<typename remove_const<typename iterator_traits<_InIter>::value_type>::type,
- typename iterator_traits<_OutIter>::value_type>::value
- && __is_cpp17_contiguous_iterator<_InIter>::value
- && __is_cpp17_contiguous_iterator<_OutIter>::value
- && is_trivially_move_assignable<__iter_value_type<_OutIter> >::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14
-pair<reverse_iterator<_InIter>, reverse_iterator<_OutIter> >
-__move_impl(reverse_iterator<_InIter> __first,
- reverse_iterator<_InIter> __last,
- reverse_iterator<_OutIter> __result) {
- auto __first_base = std::__unwrap_iter(__first.base());
- auto __last_base = std::__unwrap_iter(__last.base());
- auto __result_base = std::__unwrap_iter(__result.base());
- auto __result_first = __result_base - (__first_base - __last_base);
- std::__move_impl(__last_base, __first_base, __result_first);
- return std::make_pair(__last, reverse_iterator<_OutIter>(std::__rewrap_iter(__result.base(), __result_first)));
-}
+ template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) const {
+ using _Traits = __segmented_iterator_traits<_InIter>;
+ auto __sfirst = _Traits::__segment(__first);
+ auto __slast = _Traits::__segment(__last);
+ if (__sfirst == __slast) {
+ auto __iters = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
+ return std::make_pair(__last, std::move(__iters.second));
+ }
+
+ __result = std::__move<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__sfirst), std::move(__result)).second;
+ ++__sfirst;
+ while (__sfirst != __slast) {
+ __result =
+ std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__end(__sfirst), std::move(__result)).second;
+ ++__sfirst;
+ }
+ __result =
+ std::__move<_AlgPolicy>(_Traits::__begin(__sfirst), _Traits::__local(__last), std::move(__result)).second;
+ return std::make_pair(__last, std::move(__result));
+ }
-template <class _InIter, class _Sent, class _OutIter>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-__enable_if_t<is_copy_constructible<_InIter>::value
- && is_copy_constructible<_Sent>::value
- && is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> >
-__move(_InIter __first, _Sent __last, _OutIter __result) {
- auto __ret = std::__move_impl(std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__result));
- return std::make_pair(std::__rewrap_iter(__first, __ret.first), std::__rewrap_iter(__result, __ret.second));
-}
+ template <class _InIter,
+ class _OutIter,
+ __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value &&
+ !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) {
+ using _Traits = __segmented_iterator_traits<_OutIter>;
+ using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;
+
+ if (__first == __last)
+ return std::make_pair(std::move(__first), std::move(__result));
+
+ auto __local_first = _Traits::__local(__result);
+ auto __segment_iterator = _Traits::__segment(__result);
+ while (true) {
+ auto __local_last = _Traits::__end(__segment_iterator);
+ auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
+ auto __iters = std::__move<_AlgPolicy>(__first, __first + __size, __local_first);
+ __first = std::move(__iters.first);
+
+ if (__first == __last)
+ return std::make_pair(std::move(__first), _Traits::__compose(__segment_iterator, std::move(__iters.second)));
+
+ __local_first = _Traits::__begin(++__segment_iterator);
+ }
+ }
+};
+
+struct __move_trivial {
+ // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
+ template <class _In, class _Out,
+ __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+ operator()(_In* __first, _In* __last, _Out* __result) const {
+ return std::__copy_trivial_impl(__first, __last, __result);
+ }
+};
-template <class _InIter, class _Sent, class _OutIter>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-__enable_if_t<!is_copy_constructible<_InIter>::value
- || !is_copy_constructible<_Sent>::value
- || !is_copy_constructible<_OutIter>::value, pair<_InIter, _OutIter> >
+template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
__move(_InIter __first, _Sent __last, _OutIter __result) {
- return std::__move_impl(std::move(__first), std::move(__last), std::move(__result));
+ return std::__dispatch_copy_or_move<_AlgPolicy, __move_loop<_AlgPolicy>, __move_trivial>(
+ std::move(__first), std::move(__last), std::move(__result));
}
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
-_OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
- return std::__move(__first, __last, __result).second;
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
+move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+ static_assert(is_copy_constructible<_InputIterator>::value, "Iterators has to be copy constructible.");
+ static_assert(is_copy_constructible<_OutputIterator>::value, "The output iterator has to be copy constructible.");
+
+ return std::__move<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
}
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_MOVE_H
diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h
index a56f6b826ce3..d4f013be6807 100644
--- a/libcxx/include/__algorithm/move_backward.h
+++ b/libcxx/include/__algorithm/move_backward.h
@@ -9,71 +9,131 @@
#ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
#define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
-#include <__algorithm/unwrap_iter.h>
+#include <__algorithm/copy_move_common.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/min.h>
#include <__config>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/common_type.h>
+#include <__type_traits/is_copy_constructible.h>
#include <__utility/move.h>
-#include <cstring>
-#include <type_traits>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-_OutputIterator
-__move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
-{
- while (__first != __last)
- *--__result = _VSTD::move(*--__last);
- return __result;
-}
+template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>
+__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result);
-template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-_OutputIterator
-__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
-{
- return _VSTD::__move_backward_constexpr(__first, __last, __result);
-}
+template <class _AlgPolicy>
+struct __move_backward_loop {
+ template <class _InIter, class _Sent, class _OutIter>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result) const {
+ auto __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
+ auto __original_last_iter = __last_iter;
+
+ while (__first != __last_iter) {
+ *--__result = _IterOps<_AlgPolicy>::__iter_move(--__last_iter);
+ }
+
+ return std::make_pair(std::move(__original_last_iter), std::move(__result));
+ }
+
+ template <class _InIter, class _OutIter, __enable_if_t<__is_segmented_iterator<_InIter>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) const {
+ using _Traits = __segmented_iterator_traits<_InIter>;
+ auto __sfirst = _Traits::__segment(__first);
+ auto __slast = _Traits::__segment(__last);
+ if (__sfirst == __slast) {
+ auto __iters =
+ std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__local(__last), std::move(__result));
+ return std::make_pair(__last, __iters.second);
+ }
+
+ __result =
+ std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__local(__last), std::move(__result))
+ .second;
+ --__slast;
+ while (__sfirst != __slast) {
+ __result =
+ std::__move_backward<_AlgPolicy>(_Traits::__begin(__slast), _Traits::__end(__slast), std::move(__result))
+ .second;
+ --__slast;
+ }
+ __result = std::__move_backward<_AlgPolicy>(_Traits::__local(__first), _Traits::__end(__slast), std::move(__result))
+ .second;
+ return std::make_pair(__last, std::move(__result));
+ }
-template <class _Tp, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
-typename enable_if
-<
- is_same<typename remove_const<_Tp>::type, _Up>::value &&
- is_trivially_move_assignable<_Up>::value,
- _Up*
->::type
-__move_backward(_Tp* __first, _Tp* __last, _Up* __result)
-{
- const size_t __n = static_cast<size_t>(__last - __first);
- if (__n > 0)
- {
- __result -= __n;
- _VSTD::memmove(__result, __first, __n * sizeof(_Up));
+ template <class _InIter,
+ class _OutIter,
+ __enable_if_t<__is_cpp17_random_access_iterator<_InIter>::value &&
+ !__is_segmented_iterator<_InIter>::value && __is_segmented_iterator<_OutIter>::value,
+ int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
+ operator()(_InIter __first, _InIter __last, _OutIter __result) {
+ using _Traits = __segmented_iterator_traits<_OutIter>;
+ using _DiffT = typename common_type<__iter_diff_t<_InIter>, __iter_diff_t<_OutIter> >::type;
+
+ // When the range contains no elements, __result might not be a valid iterator
+ if (__first == __last)
+ return std::make_pair(__first, __result);
+
+ auto __orig_last = __last;
+
+ auto __local_last = _Traits::__local(__result);
+ auto __segment_iterator = _Traits::__segment(__result);
+ while (true) {
+ auto __local_first = _Traits::__begin(__segment_iterator);
+ auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first);
+ auto __iter = std::__move_backward<_AlgPolicy>(__last - __size, __last, __local_last).second;
+ __last -= __size;
+
+ if (__first == __last)
+ return std::make_pair(std::move(__orig_last), _Traits::__compose(__segment_iterator, std::move(__iter)));
+
+ __local_last = _Traits::__end(--__segment_iterator);
}
- return __result;
+ }
+};
+
+struct __move_backward_trivial {
+ // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
+ template <class _In, class _Out,
+ __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
+ operator()(_In* __first, _In* __last, _Out* __result) const {
+ return std::__copy_backward_trivial_impl(__first, __last, __result);
+ }
+};
+
+template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2>
+__move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) {
+ static_assert(std::is_copy_constructible<_BidirectionalIterator1>::value &&
+ std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible.");
+
+ return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>(
+ std::move(__first), std::move(__last), std::move(__result));
}
template <class _BidirectionalIterator1, class _BidirectionalIterator2>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_BidirectionalIterator2
-move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last,
- _BidirectionalIterator2 __result)
-{
- if (__libcpp_is_constant_evaluated()) {
- return _VSTD::__move_backward_constexpr(__first, __last, __result);
- } else {
- return _VSTD::__rewrap_iter(__result,
- _VSTD::__move_backward(_VSTD::__unwrap_iter(__first),
- _VSTD::__unwrap_iter(__last),
- _VSTD::__unwrap_iter(__result)));
- }
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _BidirectionalIterator2
+move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) {
+ return std::__move_backward<_ClassicAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)).second;
}
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
diff --git a/libcxx/include/__algorithm/next_permutation.h b/libcxx/include/__algorithm/next_permutation.h
index 05e56f4a17ff..73e8b99ab90b 100644
--- a/libcxx/include/__algorithm/next_permutation.h
+++ b/libcxx/include/__algorithm/next_permutation.h
@@ -11,10 +11,12 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/reverse.h>
#include <__config>
#include <__iterator/iterator_traits.h>
-#include <__utility/swap.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -22,44 +24,48 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Compare, class _BidirectionalIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
-__next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
+template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, bool>
+__next_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp)
{
- _BidirectionalIterator __i = __last;
+ using _Result = pair<_BidirectionalIterator, bool>;
+
+ _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
+ _BidirectionalIterator __i = __last_iter;
if (__first == __last || __first == --__i)
- return false;
+ return _Result(std::move(__last_iter), false);
+
while (true)
{
_BidirectionalIterator __ip1 = __i;
if (__comp(*--__i, *__ip1))
{
- _BidirectionalIterator __j = __last;
+ _BidirectionalIterator __j = __last_iter;
while (!__comp(*__i, *--__j))
;
- swap(*__i, *__j);
- _VSTD::reverse(__ip1, __last);
- return true;
+ _IterOps<_AlgPolicy>::iter_swap(__i, __j);
+ std::__reverse<_AlgPolicy>(__ip1, __last_iter);
+ return _Result(std::move(__last_iter), true);
}
if (__i == __first)
{
- _VSTD::reverse(__first, __last);
- return false;
+ std::__reverse<_AlgPolicy>(__first, __last_iter);
+ return _Result(std::move(__last_iter), false);
}
}
}
template <class _BidirectionalIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__next_permutation<_Comp_ref>(__first, __last, __comp);
+ return std::__next_permutation<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second;
}
template <class _BidirectionalIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last)
{
diff --git a/libcxx/include/__algorithm/none_of.h b/libcxx/include/__algorithm/none_of.h
index b34b1e00ddb8..19357eb2367c 100644
--- a/libcxx/include/__algorithm/none_of.h
+++ b/libcxx/include/__algorithm/none_of.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 bool
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
for (; __first != __last; ++__first)
if (__pred(*__first))
diff --git a/libcxx/include/__algorithm/nth_element.h b/libcxx/include/__algorithm/nth_element.h
index 688398dee814..9fdfb2cae64c 100644
--- a/libcxx/include/__algorithm/nth_element.h
+++ b/libcxx/include/__algorithm/nth_element.h
@@ -26,7 +26,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template<class _Compare, class _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 bool
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
__nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j,
_RandomAccessIterator __m, _Compare __comp)
{
@@ -42,7 +42,7 @@ __nth_element_find_guard(_RandomAccessIterator& __i, _RandomAccessIterator& __j,
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
__nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last, _Compare __comp)
{
using _Ops = _IterOps<_AlgPolicy>;
@@ -223,7 +223,7 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando
}
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last,
_Compare& __comp) {
if (__nth == __last)
@@ -231,8 +231,7 @@ void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __n
std::__debug_randomize_range<_AlgPolicy>(__first, __last);
- using _Comp_ref = typename __comp_ref_type<_Compare>::type;
- std::__nth_element<_AlgPolicy, _Comp_ref>(__first, __nth, __last, __comp);
+ std::__nth_element<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __nth, __last, __comp);
std::__debug_randomize_range<_AlgPolicy>(__first, __nth);
if (__nth != __last) {
@@ -241,14 +240,14 @@ void __nth_element_impl(_RandomAccessIterator __first, _RandomAccessIterator __n
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last,
_Compare __comp) {
std::__nth_element_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__nth), std::move(__last), __comp);
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _RandomAccessIterator __last) {
std::nth_element(std::move(__first), std::move(__nth), std::move(__last), __less<typename
iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/partial_sort.h b/libcxx/include/__algorithm/partial_sort.h
index 24016e5cf5a5..e0812affe6b5 100644
--- a/libcxx/include/__algorithm/partial_sort.h
+++ b/libcxx/include/__algorithm/partial_sort.h
@@ -29,14 +29,14 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel>
-_LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_RandomAccessIterator __partial_sort_impl(
- _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare __comp) {
+ _RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last, _Compare&& __comp) {
if (__first == __middle) {
return _IterOps<_AlgPolicy>::next(__middle, __last);
}
- std::__make_heap<_AlgPolicy, _Compare>(__first, __middle, __comp);
+ std::__make_heap<_AlgPolicy>(__first, __middle, __comp);
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __middle - __first;
_RandomAccessIterator __i = __middle;
@@ -45,17 +45,16 @@ _RandomAccessIterator __partial_sort_impl(
if (__comp(*__i, *__first))
{
_IterOps<_AlgPolicy>::iter_swap(__i, __first);
- std::__sift_down<_AlgPolicy, _Compare>(__first, __comp, __len, __first);
+ std::__sift_down<_AlgPolicy>(__first, __comp, __len, __first);
}
-
}
- std::__sort_heap<_AlgPolicy, _Compare>(std::move(__first), std::move(__middle), __comp);
+ std::__sort_heap<_AlgPolicy>(std::move(__first), std::move(__middle), __comp);
return __i;
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, class _Sentinel>
-_LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Sentinel __last,
_Compare& __comp) {
if (__first == __middle)
@@ -63,8 +62,8 @@ _RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAcces
std::__debug_randomize_range<_AlgPolicy>(__first, __last);
- using _Comp_ref = typename __comp_ref_type<_Compare>::type;
- auto __last_iter = std::__partial_sort_impl<_AlgPolicy, _Comp_ref>(__first, __middle, __last, __comp);
+ auto __last_iter =
+ std::__partial_sort_impl<_AlgPolicy>(__first, __middle, __last, static_cast<__comp_ref_type<_Compare> >(__comp));
std::__debug_randomize_range<_AlgPolicy>(__middle, __last);
@@ -72,7 +71,7 @@ _RandomAccessIterator __partial_sort(_RandomAccessIterator __first, _RandomAcces
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
_Compare __comp)
@@ -84,7 +83,7 @@ partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran
}
template <class _RandomAccessIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
partial_sort(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last)
{
diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h
index 3556764e652d..1aba07105dc8 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -13,10 +13,16 @@
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_heap.h>
+#include <__algorithm/make_projected.h>
#include <__algorithm/sift_down.h>
#include <__algorithm/sort_heap.h>
#include <__config>
+#include <__functional/identity.h>
+#include <__functional/invoke.h>
#include <__iterator/iterator_traits.h>
+#include <__type_traits/is_callable.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -24,42 +30,51 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _AlgPolicy, class _Compare, class _InputIterator, class _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _RandomAccessIterator
-__partial_sort_copy(_InputIterator __first, _InputIterator __last,
- _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
+template <class _AlgPolicy, class _Compare,
+ class _InputIterator, class _Sentinel1, class _RandomAccessIterator, class _Sentinel2,
+ class _Proj1, class _Proj2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator, _RandomAccessIterator>
+__partial_sort_copy(_InputIterator __first, _Sentinel1 __last,
+ _RandomAccessIterator __result_first, _Sentinel2 __result_last,
+ _Compare&& __comp, _Proj1&& __proj1, _Proj2&& __proj2)
{
_RandomAccessIterator __r = __result_first;
+ auto&& __projected_comp = std::__make_projected(__comp, __proj2);
+
if (__r != __result_last)
{
for (; __first != __last && __r != __result_last; ++__first, (void) ++__r)
*__r = *__first;
- std::__make_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp);
+ std::__make_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __r - __result_first;
for (; __first != __last; ++__first)
- if (__comp(*__first, *__result_first))
- {
+ if (std::__invoke(__comp, std::__invoke(__proj1, *__first), std::__invoke(__proj2, *__result_first))) {
*__result_first = *__first;
- std::__sift_down<_AlgPolicy, _Compare>(__result_first, __comp, __len, __result_first);
+ std::__sift_down<_AlgPolicy>(__result_first, __projected_comp, __len, __result_first);
}
- std::__sort_heap<_AlgPolicy, _Compare>(__result_first, __r, __comp);
+ std::__sort_heap<_AlgPolicy>(__result_first, __r, __projected_comp);
}
- return __r;
+
+ return pair<_InputIterator, _RandomAccessIterator>(
+ _IterOps<_AlgPolicy>::next(std::move(__first), std::move(__last)), std::move(__r));
}
template <class _InputIterator, class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__partial_sort_copy<_ClassicAlgPolicy, _Comp_ref>(
- __first, __last, __result_first, __result_last, __comp);
+ static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value,
+ "Comparator has to be callable");
+
+ auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last,
+ static_cast<__comp_ref_type<_Compare> >(__comp), __identity(), __identity());
+ return __result.second;
}
template <class _InputIterator, class _RandomAccessIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_RandomAccessIterator
partial_sort_copy(_InputIterator __first, _InputIterator __last,
_RandomAccessIterator __result_first, _RandomAccessIterator __result_last)
diff --git a/libcxx/include/__algorithm/partition.h b/libcxx/include/__algorithm/partition.h
index 60b4e290ebeb..0e094bf8dd92 100644
--- a/libcxx/include/__algorithm/partition.h
+++ b/libcxx/include/__algorithm/partition.h
@@ -23,7 +23,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Predicate, class _AlgPolicy, class _ForwardIterator, class _Sentinel>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_ForwardIterator, _ForwardIterator>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator, _ForwardIterator>
__partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred, forward_iterator_tag)
{
while (true)
@@ -48,7 +48,7 @@ __partition_impl(_ForwardIterator __first, _Sentinel __last, _Predicate __pred,
}
template <class _Predicate, class _AlgPolicy, class _BidirectionalIterator, class _Sentinel>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_BidirectionalIterator, _BidirectionalIterator>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator, _BidirectionalIterator>
__partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicate __pred,
bidirectional_iterator_tag)
{
@@ -76,15 +76,15 @@ __partition_impl(_BidirectionalIterator __first, _Sentinel __sentinel, _Predicat
}
template <class _AlgPolicy, class _ForwardIterator, class _Sentinel, class _Predicate, class _IterCategory>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
pair<_ForwardIterator, _ForwardIterator> __partition(
_ForwardIterator __first, _Sentinel __last, _Predicate&& __pred, _IterCategory __iter_category) {
- return std::__partition_impl<__uncvref_t<_Predicate>&, _AlgPolicy>(
+ return std::__partition_impl<__remove_cvref_t<_Predicate>&, _AlgPolicy>(
std::move(__first), std::move(__last), __pred, __iter_category);
}
template <class _ForwardIterator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator
partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
{
diff --git a/libcxx/include/__algorithm/partition_copy.h b/libcxx/include/__algorithm/partition_copy.h
index cacde0bfd47b..ff8826a93712 100644
--- a/libcxx/include/__algorithm/partition_copy.h
+++ b/libcxx/include/__algorithm/partition_copy.h
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator1,
class _OutputIterator2, class _Predicate>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 pair<_OutputIterator1, _OutputIterator2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_OutputIterator1, _OutputIterator2>
partition_copy(_InputIterator __first, _InputIterator __last,
_OutputIterator1 __out_true, _OutputIterator2 __out_false,
_Predicate __pred)
diff --git a/libcxx/include/__algorithm/partition_point.h b/libcxx/include/__algorithm/partition_point.h
index 1675534e60d5..6ede71a264cd 100644
--- a/libcxx/include/__algorithm/partition_point.h
+++ b/libcxx/include/__algorithm/partition_point.h
@@ -22,7 +22,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template<class _ForwardIterator, class _Predicate>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
partition_point(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
{
typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
diff --git a/libcxx/include/__algorithm/pop_heap.h b/libcxx/include/__algorithm/pop_heap.h
index 870af50c133e..94d32a42391b 100644
--- a/libcxx/include/__algorithm/pop_heap.h
+++ b/libcxx/include/__algorithm/pop_heap.h
@@ -27,18 +27,17 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) {
_LIBCPP_ASSERT(__len > 0, "The heap given to pop_heap must be non-empty");
- using _CompRef = typename __comp_ref_type<_Compare>::type;
- _CompRef __comp_ref = __comp;
+ __comp_ref_type<_Compare> __comp_ref = __comp;
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
if (__len > 1) {
value_type __top = _IterOps<_AlgPolicy>::__iter_move(__first); // create a hole at __first
- _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy, _CompRef>(__first, __comp_ref, __len);
+ _RandomAccessIterator __hole = std::__floyd_sift_down<_AlgPolicy>(__first, __comp_ref, __len);
--__last;
if (__hole == __last) {
@@ -47,13 +46,13 @@ void __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co
*__hole = _IterOps<_AlgPolicy>::__iter_move(__last);
++__hole;
*__last = std::move(__top);
- std::__sift_up<_AlgPolicy, _CompRef>(__first, __hole, __comp_ref, __hole - __first);
+ std::__sift_up<_AlgPolicy>(__first, __hole, __comp_ref, __hole - __first);
}
}
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@@ -63,7 +62,7 @@ void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::pop_heap(std::move(__first), std::move(__last),
__less<typename iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/prev_permutation.h b/libcxx/include/__algorithm/prev_permutation.h
index 9dbc1dad0124..0b86ab74ee01 100644
--- a/libcxx/include/__algorithm/prev_permutation.h
+++ b/libcxx/include/__algorithm/prev_permutation.h
@@ -11,10 +11,12 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/reverse.h>
#include <__config>
#include <__iterator/iterator_traits.h>
-#include <__utility/swap.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -22,44 +24,49 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Compare, class _BidirectionalIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 bool
-__prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
+template <class _AlgPolicy, class _Compare, class _BidirectionalIterator, class _Sentinel>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+pair<_BidirectionalIterator, bool>
+__prev_permutation(_BidirectionalIterator __first, _Sentinel __last, _Compare&& __comp)
{
- _BidirectionalIterator __i = __last;
+ using _Result = pair<_BidirectionalIterator, bool>;
+
+ _BidirectionalIterator __last_iter = _IterOps<_AlgPolicy>::next(__first, __last);
+ _BidirectionalIterator __i = __last_iter;
if (__first == __last || __first == --__i)
- return false;
+ return _Result(std::move(__last_iter), false);
+
while (true)
{
_BidirectionalIterator __ip1 = __i;
if (__comp(*__ip1, *--__i))
{
- _BidirectionalIterator __j = __last;
+ _BidirectionalIterator __j = __last_iter;
while (!__comp(*--__j, *__i))
;
- swap(*__i, *__j);
- _VSTD::reverse(__ip1, __last);
- return true;
+ _IterOps<_AlgPolicy>::iter_swap(__i, __j);
+ std::__reverse<_AlgPolicy>(__ip1, __last_iter);
+ return _Result(std::move(__last_iter), true);
}
if (__i == __first)
{
- _VSTD::reverse(__first, __last);
- return false;
+ std::__reverse<_AlgPolicy>(__first, __last_iter);
+ return _Result(std::move(__last_iter), false);
}
}
}
template <class _BidirectionalIterator, class _Compare>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp)
{
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return _VSTD::__prev_permutation<_Comp_ref>(__first, __last, __comp);
+ return std::__prev_permutation<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp)).second;
}
template <class _BidirectionalIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
bool
prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last)
{
diff --git a/libcxx/include/__algorithm/push_heap.h b/libcxx/include/__algorithm/push_heap.h
index 716670b76788..90684957744d 100644
--- a/libcxx/include/__algorithm/push_heap.h
+++ b/libcxx/include/__algorithm/push_heap.h
@@ -24,8 +24,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len) {
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
@@ -50,15 +50,14 @@ void __sift_up(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com
}
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
void __push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
- using _CompRef = typename __comp_ref_type<_Compare>::type;
typename iterator_traits<_RandomAccessIterator>::difference_type __len = __last - __first;
- std::__sift_up<_AlgPolicy, _CompRef>(std::move(__first), std::move(__last), __comp, __len);
+ std::__sift_up<_AlgPolicy, __comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp, __len);
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@@ -67,7 +66,7 @@ void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::push_heap(std::move(__first), std::move(__last),
__less<typename iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/ranges_adjacent_find.h b/libcxx/include/__algorithm/ranges_adjacent_find.h
index e798d568299d..d338d13e6eee 100644
--- a/libcxx/include/__algorithm/ranges_adjacent_find.h
+++ b/libcxx/include/__algorithm/ranges_adjacent_find.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -50,7 +50,7 @@ struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_binary_predicate<projected<_Iter, _Proj>, projected<_Iter, _Proj>> _Pred = ranges::equal_to>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
return __adjacent_find_impl(std::move(__first), std::move(__last), __pred, __proj);
}
@@ -59,7 +59,7 @@ struct __fn {
class _Proj = identity,
indirect_binary_predicate<projected<iterator_t<_Range>, _Proj>,
projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range> operator()(_Range&& __range, _Pred __pred = {}, _Proj __proj = {}) const {
return __adjacent_find_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -73,6 +73,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_ADJACENT_FIND_H
diff --git a/libcxx/include/__algorithm/ranges_all_of.h b/libcxx/include/__algorithm/ranges_all_of.h
index a146865652a7..e45c4e584379 100644
--- a/libcxx/include/__algorithm/ranges_all_of.h
+++ b/libcxx/include/__algorithm/ranges_all_of.h
@@ -22,7 +22,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -42,14 +42,14 @@ struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
return __all_of_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <input_range _Range, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __all_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -63,6 +63,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_ALL_OF_H
diff --git a/libcxx/include/__algorithm/ranges_any_of.h b/libcxx/include/__algorithm/ranges_any_of.h
index 11c52cbe21ea..e7d1e723a70f 100644
--- a/libcxx/include/__algorithm/ranges_any_of.h
+++ b/libcxx/include/__algorithm/ranges_any_of.h
@@ -22,7 +22,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -42,14 +42,14 @@ struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
return __any_of_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <input_range _Range, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __any_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -63,6 +63,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_ANY_OF_H
diff --git a/libcxx/include/__algorithm/ranges_binary_search.h b/libcxx/include/__algorithm/ranges_binary_search.h
index 6da68834aa3b..b2a8977652fb 100644
--- a/libcxx/include/__algorithm/ranges_binary_search.h
+++ b/libcxx/include/__algorithm/ranges_binary_search.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -33,7 +33,7 @@ namespace __binary_search {
struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
@@ -41,7 +41,7 @@ struct __fn {
template <forward_range _Range, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __r, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
@@ -58,6 +58,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_BINARY_SEARCH_H
diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h
new file mode 100644
index 000000000000..09a97fc790ea
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_clamp.h
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_CLAMP_H
+#define _LIBCPP___ALGORITHM_RANGES_CLAMP_H
+
+#include <__assert>
+#include <__config>
+#include <__functional/identity.h>
+#include <__functional/invoke.h>
+#include <__functional/ranges_operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/projected.h>
+#include <__utility/forward.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+namespace __clamp {
+struct __fn {
+
+ template <class _Type,
+ class _Proj = identity,
+ indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
+ const _Type& operator()(const _Type& __value,
+ const _Type& __low,
+ const _Type& __high,
+ _Comp __comp = {},
+ _Proj __proj = {}) const {
+ _LIBCPP_ASSERT(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))),
+ "Bad bounds passed to std::ranges::clamp");
+
+ if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low)))
+ return __low;
+ else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value)))
+ return __high;
+ else
+ return __value;
+ }
+
+};
+} // namespace __clamp
+
+inline namespace __cpo {
+ inline constexpr auto clamp = __clamp::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H
diff --git a/libcxx/include/__algorithm/ranges_copy.h b/libcxx/include/__algorithm/ranges_copy.h
index f5d6d5cd139a..bb02c84efbdb 100644
--- a/libcxx/include/__algorithm/ranges_copy.h
+++ b/libcxx/include/__algorithm/ranges_copy.h
@@ -11,6 +11,7 @@
#include <__algorithm/copy.h>
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__functional/identity.h>
#include <__iterator/concepts.h>
@@ -18,12 +19,13 @@
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -39,7 +41,7 @@ struct __fn {
requires indirectly_copyable<_InIter, _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr
copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const {
- auto __ret = std::__copy(std::move(__first), std::move(__last), std::move(__result));
+ auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
return {std::move(__ret.first), std::move(__ret.second)};
}
@@ -47,7 +49,7 @@ struct __fn {
requires indirectly_copyable<iterator_t<_Range>, _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr
copy_result<borrowed_iterator_t<_Range>, _OutIter> operator()(_Range&& __r, _OutIter __result) const {
- auto __ret = std::__copy(ranges::begin(__r), ranges::end(__r), std::move(__result));
+ auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result));
return {std::move(__ret.first), std::move(__ret.second)};
}
};
@@ -60,6 +62,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_copy_backward.h b/libcxx/include/__algorithm/ranges_copy_backward.h
index 673df8025fab..f41af66f39fb 100644
--- a/libcxx/include/__algorithm/ranges_copy_backward.h
+++ b/libcxx/include/__algorithm/ranges_copy_backward.h
@@ -14,7 +14,6 @@
#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/concepts.h>
-#include <__iterator/reverse_iterator.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
@@ -24,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -61,6 +60,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_COPY_BACKWARD_H
diff --git a/libcxx/include/__algorithm/ranges_copy_if.h b/libcxx/include/__algorithm/ranges_copy_if.h
index 492104fbbfba..dba41c3b3ab9 100644
--- a/libcxx/include/__algorithm/ranges_copy_if.h
+++ b/libcxx/include/__algorithm/ranges_copy_if.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -76,6 +76,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_COPY_IF_H
diff --git a/libcxx/include/__algorithm/ranges_copy_n.h b/libcxx/include/__algorithm/ranges_copy_n.h
index eaa05c954686..04bb80b3ba1a 100644
--- a/libcxx/include/__algorithm/ranges_copy_n.h
+++ b/libcxx/include/__algorithm/ranges_copy_n.h
@@ -11,6 +11,7 @@
#include <__algorithm/copy.h>
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/ranges_copy.h>
#include <__config>
#include <__functional/identity.h>
@@ -26,7 +27,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -51,7 +52,7 @@ struct __fn {
template <random_access_iterator _InIter, class _DiffType, random_access_iterator _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr static
copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) {
- auto __ret = std::__copy(__first, __first + __n, __result);
+ auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result);
return {__ret.first, __ret.second};
}
@@ -69,7 +70,7 @@ inline namespace __cpo {
} // namespace __cpo
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/ranges_count.h b/libcxx/include/__algorithm/ranges_count.h
index 670df26911d0..527dd0620085 100644
--- a/libcxx/include/__algorithm/ranges_count.h
+++ b/libcxx/include/__algorithm/ranges_count.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -34,7 +34,7 @@ namespace __count {
struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return __e == __value; };
return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj);
@@ -42,7 +42,7 @@ struct __fn {
template <input_range _Range, class _Type, class _Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
range_difference_t<_Range> operator()(_Range&& __r, const _Type& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return __e == __value; };
return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj);
@@ -57,6 +57,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_COUNT_H
diff --git a/libcxx/include/__algorithm/ranges_count_if.h b/libcxx/include/__algorithm/ranges_count_if.h
index 0f34ee9f2b1b..931618b7b545 100644
--- a/libcxx/include/__algorithm/ranges_count_if.h
+++ b/libcxx/include/__algorithm/ranges_count_if.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -46,14 +46,14 @@ namespace __count_if {
struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Predicate>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, _Predicate __pred, _Proj __proj = {}) const {
return ranges::__count_if_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <input_range _Range, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Predicate>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
range_difference_t<_Range> operator()(_Range&& __r, _Predicate __pred, _Proj __proj = {}) const {
return ranges::__count_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj);
}
@@ -67,6 +67,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_COUNT_IF_H
diff --git a/libcxx/include/__algorithm/ranges_equal.h b/libcxx/include/__algorithm/ranges_equal.h
index c5f2d2332216..3c417f09de90 100644
--- a/libcxx/include/__algorithm/ranges_equal.h
+++ b/libcxx/include/__algorithm/ranges_equal.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -60,7 +60,7 @@ public:
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred __pred = {},
@@ -83,7 +83,7 @@ public:
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range1&& __range1,
_Range2&& __range2,
_Pred __pred = {},
@@ -110,6 +110,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_H
diff --git a/libcxx/include/__algorithm/ranges_equal_range.h b/libcxx/include/__algorithm/ranges_equal_range.h
index dd4b377df1a1..94dc058e7bc1 100644
--- a/libcxx/include/__algorithm/ranges_equal_range.h
+++ b/libcxx/include/__algorithm/ranges_equal_range.h
@@ -24,12 +24,13 @@
#include <__ranges/subrange.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,7 +44,7 @@ struct __fn {
class _Tp,
class _Proj = identity,
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__equal_range<_RangeAlgPolicy>(
std::move(__first), std::move(__last), __value, __comp, __proj);
@@ -55,7 +56,7 @@ struct __fn {
class _Tp,
class _Proj = identity,
indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
operator()(_Range&& __range, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__equal_range<_RangeAlgPolicy>(
ranges::begin(__range), ranges::end(__range), __value, __comp, __proj);
@@ -72,6 +73,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_EQUAL_RANGE_H
diff --git a/libcxx/include/__algorithm/ranges_fill.h b/libcxx/include/__algorithm/ranges_fill.h
index 7ce4a76ba9e9..6ebc2bd67d6b 100644
--- a/libcxx/include/__algorithm/ranges_fill.h
+++ b/libcxx/include/__algorithm/ranges_fill.h
@@ -20,7 +20,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -54,6 +54,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FILL_H
diff --git a/libcxx/include/__algorithm/ranges_fill_n.h b/libcxx/include/__algorithm/ranges_fill_n.h
index d93c573406ec..a2660e8b592a 100644
--- a/libcxx/include/__algorithm/ranges_fill_n.h
+++ b/libcxx/include/__algorithm/ranges_fill_n.h
@@ -17,7 +17,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,6 +43,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FILL_N_H
diff --git a/libcxx/include/__algorithm/ranges_find.h b/libcxx/include/__algorithm/ranges_find.h
index ca6d2f438295..580c2a14c9ed 100644
--- a/libcxx/include/__algorithm/ranges_find.h
+++ b/libcxx/include/__algorithm/ranges_find.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -35,7 +35,7 @@ namespace __find {
struct __fn {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, class _Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<_Ip, _Proj>, const _Tp*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; };
return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj);
@@ -43,7 +43,7 @@ struct __fn {
template <input_range _Rp, class _Tp, class _Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Rp>, _Proj>, const _Tp*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, const _Tp& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; };
return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj);
@@ -58,6 +58,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_H
diff --git a/libcxx/include/__algorithm/ranges_find_end.h b/libcxx/include/__algorithm/ranges_find_end.h
index 270b00649848..ea36f4d4e6e7 100644
--- a/libcxx/include/__algorithm/ranges_find_end.h
+++ b/libcxx/include/__algorithm/ranges_find_end.h
@@ -21,12 +21,13 @@
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/subrange.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -39,7 +40,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred __pred = {},
@@ -64,7 +65,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range1> operator()(_Range1&& __range1,
_Range2&& __range2,
_Pred __pred = {},
@@ -92,6 +93,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_END_H
diff --git a/libcxx/include/__algorithm/ranges_find_first_of.h b/libcxx/include/__algorithm/ranges_find_first_of.h
index ae31d38e6a95..9d66e7511c0f 100644
--- a/libcxx/include/__algorithm/ranges_find_first_of.h
+++ b/libcxx/include/__algorithm/ranges_find_first_of.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -54,7 +54,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter1 operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred __pred = {},
@@ -73,7 +73,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range1> operator()(_Range1&& __range1,
_Range2&& __range2,
_Pred __pred = {},
@@ -96,6 +96,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_FIRST_OF_H
diff --git a/libcxx/include/__algorithm/ranges_find_if.h b/libcxx/include/__algorithm/ranges_find_if.h
index 65ac122f6677..45ce6e460d68 100644
--- a/libcxx/include/__algorithm/ranges_find_if.h
+++ b/libcxx/include/__algorithm/ranges_find_if.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -45,14 +45,14 @@ struct __fn {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
indirect_unary_predicate<projected<_Ip, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const {
return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <input_range _Rp, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const {
return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred, __proj);
}
@@ -66,6 +66,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_H
diff --git a/libcxx/include/__algorithm/ranges_find_if_not.h b/libcxx/include/__algorithm/ranges_find_if_not.h
index 9a1adf71fc58..3dd12132754b 100644
--- a/libcxx/include/__algorithm/ranges_find_if_not.h
+++ b/libcxx/include/__algorithm/ranges_find_if_not.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -35,7 +35,7 @@ namespace __find_if_not {
struct __fn {
template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
indirect_unary_predicate<projected<_Ip, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Ip operator()(_Ip __first, _Sp __last, _Pred __pred, _Proj __proj = {}) const {
auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward<decltype(__e)>(__e)); };
return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred2, __proj);
@@ -43,7 +43,7 @@ struct __fn {
template <input_range _Rp, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Rp>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Pred __pred, _Proj __proj = {}) const {
auto __pred2 = [&](auto&& __e) { return !std::invoke(__pred, std::forward<decltype(__e)>(__e)); };
return ranges::__find_if_impl(ranges::begin(__r), ranges::end(__r), __pred2, __proj);
@@ -58,6 +58,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FIND_IF_NOT_H
diff --git a/libcxx/include/__algorithm/ranges_for_each.h b/libcxx/include/__algorithm/ranges_for_each.h
index f284c0ee3ad4..0c70c05981a7 100644
--- a/libcxx/include/__algorithm/ranges_for_each.h
+++ b/libcxx/include/__algorithm/ranges_for_each.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -73,6 +73,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H
diff --git a/libcxx/include/__algorithm/ranges_for_each_n.h b/libcxx/include/__algorithm/ranges_for_each_n.h
index 013afbd19389..261816aba436 100644
--- a/libcxx/include/__algorithm/ranges_for_each_n.h
+++ b/libcxx/include/__algorithm/ranges_for_each_n.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -61,6 +61,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H
diff --git a/libcxx/include/__algorithm/ranges_generate.h b/libcxx/include/__algorithm/ranges_generate.h
index 149296574d80..ae486ae65395 100644
--- a/libcxx/include/__algorithm/ranges_generate.h
+++ b/libcxx/include/__algorithm/ranges_generate.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -68,6 +68,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_H
diff --git a/libcxx/include/__algorithm/ranges_generate_n.h b/libcxx/include/__algorithm/ranges_generate_n.h
index 63f466cecdd7..e625e3a97428 100644
--- a/libcxx/include/__algorithm/ranges_generate_n.h
+++ b/libcxx/include/__algorithm/ranges_generate_n.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -57,6 +57,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_GENERATE_N_H
diff --git a/libcxx/include/__algorithm/ranges_includes.h b/libcxx/include/__algorithm/ranges_includes.h
index 2c7581af68af..8438117cfa80 100644
--- a/libcxx/include/__algorithm/ranges_includes.h
+++ b/libcxx/include/__algorithm/ranges_includes.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,7 +43,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity,
indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
@@ -68,7 +68,7 @@ struct __fn {
class _Proj2 = identity,
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>>
_Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
return std::__includes(
ranges::begin(__range1),
@@ -90,6 +90,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_INCLUDES_H
diff --git a/libcxx/include/__algorithm/ranges_inplace_merge.h b/libcxx/include/__algorithm/ranges_inplace_merge.h
index a0867e486c3a..88171a65c8e9 100644
--- a/libcxx/include/__algorithm/ranges_inplace_merge.h
+++ b/libcxx/include/__algorithm/ranges_inplace_merge.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H
#include <__algorithm/inplace_merge.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__config>
#include <__functional/identity.h>
@@ -17,6 +18,7 @@
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
+#include <__iterator/next.h>
#include <__iterator/projected.h>
#include <__iterator/sortable.h>
#include <__ranges/access.h>
@@ -29,35 +31,45 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __inplace_merge {
-struct __fn {
+ struct __fn {
+ template <class _Iter, class _Sent, class _Comp, class _Proj>
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto
+ __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) {
+ auto __last_iter = ranges::next(__middle, __last);
+ std::__inplace_merge<_RangeAlgPolicy>(
+ std::move(__first), std::move(__middle), __last_iter, std::__make_projected(__comp, __proj));
+ return __last_iter;
+ }
- template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
- requires sortable<_Iter, _Comp, _Proj>
- _LIBCPP_HIDE_FROM_ABI
- _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__middle; (void)__last; (void)__comp; (void)__proj;
- return {};
- }
+ template <
+ bidirectional_iterator _Iter,
+ sentinel_for<_Iter> _Sent,
+ class _Comp = ranges::less,
+ class _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ _LIBCPP_HIDE_FROM_ABI _Iter
+ operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
+ return __inplace_merge_impl(
+ std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj));
+ }
- template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
- requires sortable<iterator_t<_Range>, _Comp, _Proj>
- _LIBCPP_HIDE_FROM_ABI
- borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle,
- _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__middle; (void)__comp; (void)__proj;
- return {};
- }
-
-};
+ template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
+ requires sortable<
+ iterator_t<_Range>,
+ _Comp,
+ _Proj> _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range>
+ operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const {
+ return __inplace_merge_impl(
+ ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj));
+ }
+ };
} // namespace __inplace_merge
@@ -68,6 +80,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_INPLACE_MERGE_H
diff --git a/libcxx/include/__algorithm/ranges_is_heap.h b/libcxx/include/__algorithm/ranges_is_heap.h
index a3e86d1a8d72..a16c075b0763 100644
--- a/libcxx/include/__algorithm/ranges_is_heap.h
+++ b/libcxx/include/__algorithm/ranges_is_heap.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -39,7 +39,7 @@ struct __fn {
_LIBCPP_HIDE_FROM_ABI constexpr
static bool __is_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
auto __result = std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp);
return __result == __last;
@@ -47,14 +47,14 @@ struct __fn {
template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
return __is_heap_fn_impl(std::move(__first), std::move(__last), __comp, __proj);
}
template <random_access_range _Range, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
return __is_heap_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj);
}
@@ -69,6 +69,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_H
diff --git a/libcxx/include/__algorithm/ranges_is_heap_until.h b/libcxx/include/__algorithm/ranges_is_heap_until.h
index bcd33ad404e8..8c8dac5bc909 100644
--- a/libcxx/include/__algorithm/ranges_is_heap_until.h
+++ b/libcxx/include/__algorithm/ranges_is_heap_until.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -40,21 +40,21 @@ struct __fn {
_LIBCPP_HIDE_FROM_ABI constexpr
static _Iter __is_heap_until_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
return std::__is_heap_until(std::move(__first), std::move(__last_iter), __projected_comp);
}
template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
return __is_heap_until_fn_impl(std::move(__first), std::move(__last), __comp, __proj);
}
template <random_access_range _Range, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
return __is_heap_until_fn_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj);
}
@@ -70,6 +70,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_IS_HEAP_UNTIL_H
diff --git a/libcxx/include/__algorithm/ranges_is_partitioned.h b/libcxx/include/__algorithm/ranges_is_partitioned.h
index 3d572895ebe1..b903953d6165 100644
--- a/libcxx/include/__algorithm/ranges_is_partitioned.h
+++ b/libcxx/include/__algorithm/ranges_is_partitioned.h
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -54,7 +54,7 @@ struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
return __is_parititioned_impl(std::move(__first), std::move(__last), __pred, __proj);
}
@@ -62,7 +62,7 @@ struct __fn {
template <input_range _Range,
class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __is_parititioned_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -76,6 +76,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_IS_PARTITIONED_H
diff --git a/libcxx/include/__algorithm/ranges_is_permutation.h b/libcxx/include/__algorithm/ranges_is_permutation.h
new file mode 100644
index 000000000000..b617500ea0d8
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_is_permutation.h
@@ -0,0 +1,89 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H
+#define _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H
+
+#include <__algorithm/is_permutation.h>
+#include <__algorithm/iterator_operations.h>
+#include <__config>
+#include <__functional/identity.h>
+#include <__functional/ranges_operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/distance.h>
+#include <__iterator/projected.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+namespace __is_permutation {
+struct __fn {
+
+ template <class _Iter1, class _Sent1, class _Iter2, class _Sent2,
+ class _Proj1, class _Proj2, class _Pred>
+ _LIBCPP_HIDE_FROM_ABI constexpr static
+ bool __is_permutation_func_impl(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+ return std::__is_permutation<_RangeAlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __proj1, __proj2);
+ }
+
+ template <forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
+ forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
+ class _Proj1 = identity,
+ class _Proj2 = identity,
+ indirect_equivalence_relation<projected<_Iter1, _Proj1>,
+ projected<_Iter2, _Proj2>> _Pred = ranges::equal_to>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
+ bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
+ return __is_permutation_func_impl(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2),
+ __pred, __proj1, __proj2);
+ }
+
+ template <forward_range _Range1,
+ forward_range _Range2,
+ class _Proj1 = identity,
+ class _Proj2 = identity,
+ indirect_equivalence_relation<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
+ bool operator()(_Range1&& __range1, _Range2&& __range2,
+ _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
+ if constexpr (sized_range<_Range1> && sized_range<_Range2>) {
+ if (ranges::distance(__range1) != ranges::distance(__range2))
+ return false;
+ }
+
+ return __is_permutation_func_impl(
+ ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), ranges::end(__range2),
+ __pred, __proj1, __proj2);
+ }
+};
+} // namespace __is_permutation
+
+inline namespace __cpo {
+ inline constexpr auto is_permutation = __is_permutation::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_IS_PERMUTATION_H
diff --git a/libcxx/include/__algorithm/ranges_is_sorted.h b/libcxx/include/__algorithm/ranges_is_sorted.h
index 938e69afba8d..ce3032ff226e 100644
--- a/libcxx/include/__algorithm/ranges_is_sorted.h
+++ b/libcxx/include/__algorithm/ranges_is_sorted.h
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -33,7 +33,7 @@ struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
return ranges::__is_sorted_until_impl(std::move(__first), __last, __comp, __proj) == __last;
}
@@ -41,7 +41,7 @@ struct __fn {
template <forward_range _Range,
class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
auto __last = ranges::end(__range);
return ranges::__is_sorted_until_impl(ranges::begin(__range), __last, __comp, __proj) == __last;
@@ -56,6 +56,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_H
diff --git a/libcxx/include/__algorithm/ranges_is_sorted_until.h b/libcxx/include/__algorithm/ranges_is_sorted_until.h
index c8f0608e1255..17fc42e97fd3 100644
--- a/libcxx/include/__algorithm/ranges_is_sorted_until.h
+++ b/libcxx/include/__algorithm/ranges_is_sorted_until.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -49,7 +49,7 @@ struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
return ranges::__is_sorted_until_impl(std::move(__first), std::move(__last), __comp, __proj);
}
@@ -57,7 +57,7 @@ struct __fn {
template <forward_range _Range,
class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
return ranges::__is_sorted_until_impl(ranges::begin(__range), ranges::end(__range), __comp, __proj);
}
@@ -71,6 +71,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP__ALGORITHM_RANGES_IS_SORTED_UNTIL_H
diff --git a/libcxx/include/__algorithm/ranges_iterator_concept.h b/libcxx/include/__algorithm/ranges_iterator_concept.h
index 3323119317ae..3ac6b317031a 100644
--- a/libcxx/include/__algorithm/ranges_iterator_concept.h
+++ b/libcxx/include/__algorithm/ranges_iterator_concept.h
@@ -12,13 +12,13 @@
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
-#include <type_traits>
+#include <__type_traits/remove_cvref.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -26,7 +26,7 @@ namespace ranges {
template <class _IterMaybeQualified>
consteval auto __get_iterator_concept() {
- using _Iter = __uncvref_t<_IterMaybeQualified>;
+ using _Iter = __remove_cvref_t<_IterMaybeQualified>;
if constexpr (contiguous_iterator<_Iter>)
return contiguous_iterator_tag();
@@ -46,6 +46,6 @@ using __iterator_concept = decltype(__get_iterator_concept<_Iter>());
} // namespace ranges
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_ITERATOR_CONCEPT_H
diff --git a/libcxx/include/__algorithm/ranges_lexicographical_compare.h b/libcxx/include/__algorithm/ranges_lexicographical_compare.h
index fe709f7a7f70..2972e327169d 100644
--- a/libcxx/include/__algorithm/ranges_lexicographical_compare.h
+++ b/libcxx/include/__algorithm/ranges_lexicographical_compare.h
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -55,7 +55,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity,
indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Comp __comp = {},
@@ -74,7 +74,7 @@ struct __fn {
class _Proj2 = identity,
indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
projected<iterator_t<_Range2>, _Proj2>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range1&& __range1, _Range2&& __range2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
return __lexicographical_compare_impl(ranges::begin(__range1), ranges::end(__range1),
ranges::begin(__range2), ranges::end(__range2),
@@ -93,6 +93,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_LEXICOGRAPHICAL_COMPARE_H
diff --git a/libcxx/include/__algorithm/ranges_lower_bound.h b/libcxx/include/__algorithm/ranges_lower_bound.h
index 1a9ae204a1ee..78cbb6d4fb24 100644
--- a/libcxx/include/__algorithm/ranges_lower_bound.h
+++ b/libcxx/include/__algorithm/ranges_lower_bound.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -37,14 +37,14 @@ namespace __lower_bound {
struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
return std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
}
template <forward_range _Range, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range> operator()(_Range&& __r,
const _Type& __value,
_Comp __comp = {},
@@ -61,6 +61,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_LOWER_BOUND_H
diff --git a/libcxx/include/__algorithm/ranges_make_heap.h b/libcxx/include/__algorithm/ranges_make_heap.h
index 8eabdd12cd2f..f25c7ab58888 100644
--- a/libcxx/include/__algorithm/ranges_make_heap.h
+++ b/libcxx/include/__algorithm/ranges_make_heap.h
@@ -32,7 +32,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -45,7 +45,7 @@ struct __fn {
_Iter __make_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__make_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
return __last_iter;
@@ -75,6 +75,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MAKE_HEAP_H
diff --git a/libcxx/include/__algorithm/ranges_max.h b/libcxx/include/__algorithm/ranges_max.h
index f48bc3ececa2..55aef997698c 100644
--- a/libcxx/include/__algorithm/ranges_max.h
+++ b/libcxx/include/__algorithm/ranges_max.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
@@ -39,14 +39,14 @@ namespace __max {
struct __fn {
template <class _Tp, class _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const {
return std::invoke(__comp, std::invoke(__proj, __a), std::invoke(__proj, __b)) ? __b : __a;
}
template <copyable _Tp, class _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const {
_LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element");
@@ -57,7 +57,7 @@ struct __fn {
template <input_range _Rp, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
@@ -88,6 +88,6 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
-#endif // _LIBCPP_STD_VER > 17 && && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17 &&
#endif // _LIBCPP___ALGORITHM_RANGES_MAX_H
diff --git a/libcxx/include/__algorithm/ranges_max_element.h b/libcxx/include/__algorithm/ranges_max_element.h
index d8d7242e176b..490f32075a4c 100644
--- a/libcxx/include/__algorithm/ranges_max_element.h
+++ b/libcxx/include/__algorithm/ranges_max_element.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -33,7 +33,7 @@ namespace __max_element {
struct __fn {
template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); };
return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj);
@@ -41,7 +41,7 @@ struct __fn {
template <forward_range _Rp, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) { return std::invoke(__comp, __rhs, __lhs); };
return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj);
@@ -56,6 +56,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H
diff --git a/libcxx/include/__algorithm/ranges_merge.h b/libcxx/include/__algorithm/ranges_merge.h
index c73e09e94ccc..b36a05abc41e 100644
--- a/libcxx/include/__algorithm/ranges_merge.h
+++ b/libcxx/include/__algorithm/ranges_merge.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -47,7 +47,7 @@ template <
class _Comp,
class _Proj1,
class _Proj2>
-_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__uncvref_t<_InIter1>, __uncvref_t<_InIter2>, __uncvref_t<_OutIter>>
+_LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, __remove_cvref_t<_InIter2>, __remove_cvref_t<_OutIter>>
__merge_impl(
_InIter1&& __first1,
_Sent1&& __last1,
@@ -107,7 +107,7 @@ struct __fn {
_OutIter,
_Comp,
_Proj1,
- _Proj2>
+ _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr merge_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter>
operator()(
_Range1&& __range1,
@@ -137,6 +137,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H
diff --git a/libcxx/include/__algorithm/ranges_min.h b/libcxx/include/__algorithm/ranges_min.h
index 0bb1e72ac5ac..0e31f57fb8dd 100644
--- a/libcxx/include/__algorithm/ranges_min.h
+++ b/libcxx/include/__algorithm/ranges_min.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
@@ -38,14 +38,14 @@ namespace __min {
struct __fn {
template <class _Tp, class _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const {
return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a;
}
template <copyable _Tp, class _Proj = identity,
indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Tp operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const {
_LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list must contain at least one element");
return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj);
@@ -54,7 +54,7 @@ struct __fn {
template <input_range _Rp, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
range_value_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
@@ -84,6 +84,6 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
-#endif // _LIBCPP_STD_VER > 17 && && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17 &&
#endif // _LIBCPP___ALGORITHM_RANGES_MIN_H
diff --git a/libcxx/include/__algorithm/ranges_min_element.h b/libcxx/include/__algorithm/ranges_min_element.h
index 26f95fe3a6d2..1751874d03bb 100644
--- a/libcxx/include/__algorithm/ranges_min_element.h
+++ b/libcxx/include/__algorithm/ranges_min_element.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -48,14 +48,14 @@ namespace __min_element {
struct __fn {
template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Ip operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
return ranges::__min_element_impl(__first, __last, __comp, __proj);
}
template <forward_range _Rp, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Rp> operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj);
}
@@ -69,6 +69,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H
diff --git a/libcxx/include/__algorithm/ranges_minmax.h b/libcxx/include/__algorithm/ranges_minmax.h
index 2f4bba0e7cc0..f82e00551e47 100644
--- a/libcxx/include/__algorithm/ranges_minmax.h
+++ b/libcxx/include/__algorithm/ranges_minmax.h
@@ -23,13 +23,14 @@
#include <__ranges/concepts.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#include <initializer_list>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
@@ -44,7 +45,7 @@ namespace __minmax {
struct __fn {
template <class _Type, class _Proj = identity,
indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<const _Type&>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr ranges::minmax_result<const _Type&>
operator()(const _Type& __a, const _Type& __b, _Comp __comp = {}, _Proj __proj = {}) const {
if (std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)))
return {__b, __a};
@@ -53,7 +54,7 @@ struct __fn {
template <copyable _Type, class _Proj = identity,
indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
ranges::minmax_result<_Type> operator()(initializer_list<_Type> __il, _Comp __comp = {}, _Proj __proj = {}) const {
_LIBCPP_ASSERT(__il.begin() != __il.end(), "initializer_list has to contain at least one element");
auto __iters = std::__minmax_element_impl(__il.begin(), __il.end(), __comp, __proj);
@@ -63,7 +64,7 @@ struct __fn {
template <input_range _Range, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
ranges::minmax_result<range_value_t<_Range>> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
@@ -128,6 +129,6 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H
diff --git a/libcxx/include/__algorithm/ranges_minmax_element.h b/libcxx/include/__algorithm/ranges_minmax_element.h
index b7bb26cefe95..6699f9626e1b 100644
--- a/libcxx/include/__algorithm/ranges_minmax_element.h
+++ b/libcxx/include/__algorithm/ranges_minmax_element.h
@@ -29,7 +29,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -42,7 +42,7 @@ namespace __minmax_element {
struct __fn {
template <forward_iterator _Ip, sentinel_for<_Ip> _Sp, class _Proj = identity,
indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
ranges::minmax_element_result<_Ip> operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__minmax_element_impl(std::move(__first), std::move(__last), __comp, __proj);
return {__ret.first, __ret.second};
@@ -50,7 +50,7 @@ struct __fn {
template <forward_range _Rp, class _Proj = identity,
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
ranges::minmax_element_result<borrowed_iterator_t<_Rp>>
operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__minmax_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj);
@@ -67,6 +67,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MINMAX_H
diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h
index 4c1440b5da06..4fd051792838 100644
--- a/libcxx/include/__algorithm/ranges_mismatch.h
+++ b/libcxx/include/__algorithm/ranges_mismatch.h
@@ -27,7 +27,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
namespace ranges {
@@ -55,7 +55,7 @@ struct __fn {
input_iterator _I2, sentinel_for<_I2> _S2,
class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity>
requires indirectly_comparable<_I1, _I2, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
mismatch_result<_I1, _I2> operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2,
_Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
return __go(std::move(__first1), __last1, std::move(__first2), __last2, __pred, __proj1, __proj2);
@@ -64,7 +64,7 @@ struct __fn {
template <input_range _R1, input_range _R2,
class _Pred = ranges::equal_to, class _Proj1 = identity, class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_R1>, iterator_t<_R2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
mismatch_result<borrowed_iterator_t<_R1>, borrowed_iterator_t<_R2>>
operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
return __go(ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2),
@@ -78,7 +78,7 @@ inline namespace __cpo {
} // namespace __cpo
} // namespace ranges
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/ranges_move.h b/libcxx/include/__algorithm/ranges_move.h
index ad4342d7c989..46a0970f834a 100644
--- a/libcxx/include/__algorithm/ranges_move.h
+++ b/libcxx/include/__algorithm/ranges_move.h
@@ -10,10 +10,10 @@
#define _LIBCPP___ALGORITHM_RANGES_MOVE_H
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/move.h>
#include <__config>
#include <__iterator/concepts.h>
-#include <__iterator/iter_move.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -36,24 +36,12 @@ namespace __move {
struct __fn {
template <class _InIter, class _Sent, class _OutIter>
- requires __iter_move::__move_deref<_InIter> // check that we are allowed to std::move() the value
_LIBCPP_HIDE_FROM_ABI constexpr static
move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
- auto __ret = std::__move(std::move(__first), std::move(__last), std::move(__result));
+ auto __ret = std::__move<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
return {std::move(__ret.first), std::move(__ret.second)};
}
- template <class _InIter, class _Sent, class _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr static
- move_result<_InIter, _OutIter> __move_impl(_InIter __first, _Sent __last, _OutIter __result) {
- while (__first != __last) {
- *__result = ranges::iter_move(__first);
- ++__first;
- ++__result;
- }
- return {std::move(__first), std::move(__result)};
- }
-
template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter>
requires indirectly_movable<_InIter, _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr
@@ -78,6 +66,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MOVE_H
diff --git a/libcxx/include/__algorithm/ranges_move_backward.h b/libcxx/include/__algorithm/ranges_move_backward.h
index b3dfa7139603..d4e8eb1a5008 100644
--- a/libcxx/include/__algorithm/ranges_move_backward.h
+++ b/libcxx/include/__algorithm/ranges_move_backward.h
@@ -10,12 +10,12 @@
#define _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H
#include <__algorithm/in_out_result.h>
-#include <__algorithm/ranges_move.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/move_backward.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iter_move.h>
#include <__iterator/next.h>
-#include <__iterator/reverse_iterator.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -40,10 +40,8 @@ struct __fn {
template <class _InIter, class _Sent, class _OutIter>
_LIBCPP_HIDE_FROM_ABI constexpr static
move_backward_result<_InIter, _OutIter> __move_backward_impl(_InIter __first, _Sent __last, _OutIter __result) {
- auto __ret = ranges::move(std::make_reverse_iterator(ranges::next(__first, __last)),
- std::make_reverse_iterator(__first),
- std::make_reverse_iterator(__result));
- return {std::move(__ret.in.base()), std::move(__ret.out.base())};
+ auto __ret = std::__move_backward<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result));
+ return {std::move(__ret.first), std::move(__ret.second)};
}
template <bidirectional_iterator _InIter, sentinel_for<_InIter> _Sent, bidirectional_iterator _OutIter>
@@ -70,6 +68,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_MOVE_BACKWARD_H
diff --git a/libcxx/include/__algorithm/ranges_next_permutation.h b/libcxx/include/__algorithm/ranges_next_permutation.h
new file mode 100644
index 000000000000..6c8e8e1529f2
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_next_permutation.h
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H
+#define _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H
+
+#include <__algorithm/in_found_result.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/make_projected.h>
+#include <__algorithm/next_permutation.h>
+#include <__config>
+#include <__functional/identity.h>
+#include <__functional/ranges_operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/sortable.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+
+template <class _InIter>
+using next_permutation_result = in_found_result<_InIter>;
+
+namespace __next_permutation {
+
+struct __fn {
+ template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result<_Iter>
+ operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __result = std::__next_permutation<_RangeAlgPolicy>(
+ std::move(__first), std::move(__last), std::__make_projected(__comp, __proj));
+ return {std::move(__result.first), std::move(__result.second)};
+ }
+
+ template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ _LIBCPP_HIDE_FROM_ABI constexpr next_permutation_result<borrowed_iterator_t<_Range>>
+ operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __result = std::__next_permutation<_RangeAlgPolicy>(
+ ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj));
+ return {std::move(__result.first), std::move(__result.second)};
+ }
+};
+
+} // namespace __next_permutation
+
+inline namespace __cpo {
+constexpr inline auto next_permutation = __next_permutation::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_NEXT_PERMUTATION_H
diff --git a/libcxx/include/__algorithm/ranges_none_of.h b/libcxx/include/__algorithm/ranges_none_of.h
index 706ff5cd741d..b39e570fd33a 100644
--- a/libcxx/include/__algorithm/ranges_none_of.h
+++ b/libcxx/include/__algorithm/ranges_none_of.h
@@ -22,7 +22,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -42,14 +42,14 @@ struct __fn {
template <input_iterator _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const {
return __none_of_impl(std::move(__first), std::move(__last), __pred, __proj);
}
template <input_range _Range, class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return __none_of_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -63,6 +63,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_NONE_OF_H
diff --git a/libcxx/include/__algorithm/ranges_nth_element.h b/libcxx/include/__algorithm/ranges_nth_element.h
index b15eb816b918..d9ec4f13825b 100644
--- a/libcxx/include/__algorithm/ranges_nth_element.h
+++ b/libcxx/include/__algorithm/ranges_nth_element.h
@@ -31,7 +31,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -44,7 +44,7 @@ struct __fn {
_Iter __nth_element_fn_impl(_Iter __first, _Iter __nth, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__nth_element_impl<_RangeAlgPolicy>(std::move(__first), std::move(__nth), __last_iter, __projected_comp);
return __last_iter;
@@ -75,6 +75,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_NTH_ELEMENT_H
diff --git a/libcxx/include/__algorithm/ranges_partial_sort.h b/libcxx/include/__algorithm/ranges_partial_sort.h
index 5e82bc6fcc32..3ea0a7fb44b5 100644
--- a/libcxx/include/__algorithm/ranges_partial_sort.h
+++ b/libcxx/include/__algorithm/ranges_partial_sort.h
@@ -27,12 +27,13 @@
#include <__ranges/dangling.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,7 +44,7 @@ struct __fn {
template <class _Iter, class _Sent, class _Comp, class _Proj>
_LIBCPP_HIDE_FROM_ABI constexpr static
_Iter __partial_sort_fn_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp& __comp, _Proj& __proj) {
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
return std::__partial_sort<_RangeAlgPolicy>(std::move(__first), std::move(__middle), __last, __projected_comp);
}
@@ -72,6 +73,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_H
diff --git a/libcxx/include/__algorithm/ranges_partial_sort_copy.h b/libcxx/include/__algorithm/ranges_partial_sort_copy.h
index 55ad2ca4e686..212db555a8d3 100644
--- a/libcxx/include/__algorithm/ranges_partial_sort_copy.h
+++ b/libcxx/include/__algorithm/ranges_partial_sort_copy.h
@@ -10,11 +10,11 @@
#define _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/partial_sort_copy.h>
#include <__config>
#include <__functional/identity.h>
-#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
@@ -23,14 +23,14 @@
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
-#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -52,9 +52,11 @@ struct __fn {
partial_sort_copy_result<_Iter1, _Iter2>
operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result_first, _Sent2 __result_last,
_Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result_first; (void)__result_last; (void)__comp; (void)__proj1; (void)__proj2;
- return {};
+ auto __result = std::__partial_sort_copy<_RangeAlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__result_first), std::move(__result_last),
+ __comp, __proj1, __proj2
+ );
+ return {std::move(__result.first), std::move(__result.second)};
}
template <input_range _Range1, random_access_range _Range2, class _Comp = ranges::less,
@@ -67,9 +69,11 @@ struct __fn {
partial_sort_copy_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>>
operator()(_Range1&& __range, _Range2&& __result_range, _Comp __comp = {},
_Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
- // TODO: implement
- (void)__range; (void)__result_range; (void)__comp; (void)__proj1; (void)__proj2;
- return {};
+ auto __result = std::__partial_sort_copy<_RangeAlgPolicy>(
+ ranges::begin(__range), ranges::end(__range), ranges::begin(__result_range), ranges::end(__result_range),
+ __comp, __proj1, __proj2
+ );
+ return {std::move(__result.first), std::move(__result.second)};
}
};
@@ -83,6 +87,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PARTIAL_SORT_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_partition.h b/libcxx/include/__algorithm/ranges_partition.h
index 60bee699d90e..8b3aae5c250d 100644
--- a/libcxx/include/__algorithm/ranges_partition.h
+++ b/libcxx/include/__algorithm/ranges_partition.h
@@ -26,13 +26,14 @@
#include <__ranges/subrange.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,8 +44,8 @@ struct __fn {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI static constexpr
- subrange<__uncvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
- auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj);
+ subrange<__remove_cvref_t<_Iter>> __partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
+ auto&& __projected_pred = std::__make_projected(__pred, __proj);
auto __result = std::__partition<_RangeAlgPolicy>(
std::move(__first), std::move(__last), __projected_pred, __iterator_concept<_Iter>());
@@ -77,6 +78,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_H
diff --git a/libcxx/include/__algorithm/ranges_partition_copy.h b/libcxx/include/__algorithm/ranges_partition_copy.h
index 7201a8cbfe45..e7a9a347df5a 100644
--- a/libcxx/include/__algorithm/ranges_partition_copy.h
+++ b/libcxx/include/__algorithm/ranges_partition_copy.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -43,7 +43,7 @@ struct __fn {
template <class _InIter, class _Sent, class _OutIter1, class _OutIter2, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI constexpr
static partition_copy_result<
- __uncvref_t<_InIter>, __uncvref_t<_OutIter1>, __uncvref_t<_OutIter2>
+ __remove_cvref_t<_InIter>, __remove_cvref_t<_OutIter1>, __remove_cvref_t<_OutIter2>
> __partition_copy_fn_impl( _InIter&& __first, _Sent&& __last, _OutIter1&& __out_true, _OutIter2&& __out_false,
_Pred& __pred, _Proj& __proj) {
for (; __first != __last; ++__first) {
@@ -93,6 +93,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_partition_point.h b/libcxx/include/__algorithm/ranges_partition_point.h
index 6614a0bb50fd..2bd118d4def0 100644
--- a/libcxx/include/__algorithm/ranges_partition_point.h
+++ b/libcxx/include/__algorithm/ranges_partition_point.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -83,6 +83,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PARTITION_POINT_H
diff --git a/libcxx/include/__algorithm/ranges_pop_heap.h b/libcxx/include/__algorithm/ranges_pop_heap.h
index 92df6119d34a..65beec886441 100644
--- a/libcxx/include/__algorithm/ranges_pop_heap.h
+++ b/libcxx/include/__algorithm/ranges_pop_heap.h
@@ -32,7 +32,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -46,7 +46,7 @@ struct __fn {
auto __last_iter = ranges::next(__first, __last);
auto __len = __last_iter - __first;
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__pop_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp, __len);
return __last_iter;
@@ -76,6 +76,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_POP_HEAP_H
diff --git a/libcxx/include/__algorithm/ranges_prev_permutation.h b/libcxx/include/__algorithm/ranges_prev_permutation.h
new file mode 100644
index 000000000000..6866d90cf484
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_prev_permutation.h
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H
+#define _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H
+
+#include <__algorithm/in_found_result.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/make_projected.h>
+#include <__algorithm/prev_permutation.h>
+#include <__config>
+#include <__functional/identity.h>
+#include <__functional/ranges_operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/sortable.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+
+template <class _InIter>
+using prev_permutation_result = in_found_result<_InIter>;
+
+namespace __prev_permutation {
+
+struct __fn {
+
+ template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+ class _Comp = ranges::less, class _Proj = identity>
+ requires sortable<_Iter, _Comp, _Proj>
+ _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<_Iter>
+ operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __result = std::__prev_permutation<_RangeAlgPolicy>(
+ std::move(__first), std::move(__last), std::__make_projected(__comp, __proj));
+ return {std::move(__result.first), std::move(__result.second)};
+ }
+
+ template <bidirectional_range _Range,
+ class _Comp = ranges::less, class _Proj = identity>
+ requires sortable<iterator_t<_Range>, _Comp, _Proj>
+ _LIBCPP_HIDE_FROM_ABI constexpr prev_permutation_result<borrowed_iterator_t<_Range>>
+ operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __result = std::__prev_permutation<_RangeAlgPolicy>(
+ ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj));
+ return {std::move(__result.first), std::move(__result.second)};
+ }
+
+};
+
+} // namespace __prev_permutation
+
+inline namespace __cpo {
+constexpr inline auto prev_permutation = __prev_permutation::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_PREV_PERMUTATION_H
diff --git a/libcxx/include/__algorithm/ranges_push_heap.h b/libcxx/include/__algorithm/ranges_push_heap.h
index 4c41b00128de..a1f434741762 100644
--- a/libcxx/include/__algorithm/ranges_push_heap.h
+++ b/libcxx/include/__algorithm/ranges_push_heap.h
@@ -32,7 +32,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -45,7 +45,7 @@ struct __fn {
_Iter __push_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__push_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
return __last_iter;
@@ -75,6 +75,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_PUSH_HEAP_H
diff --git a/libcxx/include/__algorithm/ranges_remove.h b/libcxx/include/__algorithm/ranges_remove.h
index a6a1200763d2..dd5c5fb4536a 100644
--- a/libcxx/include/__algorithm/ranges_remove.h
+++ b/libcxx/include/__algorithm/ranges_remove.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -35,7 +35,7 @@ struct __fn {
template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Type& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __other) { return __value == __other; };
return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj);
@@ -44,7 +44,7 @@ struct __fn {
template <forward_range _Range, class _Type, class _Proj = identity>
requires permutable<iterator_t<_Range>>
&& indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range> operator()(_Range&& __range, const _Type& __value, _Proj __proj = {}) const {
auto __pred = [&](auto&& __other) { return __value == __other; };
return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
@@ -59,6 +59,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_H
diff --git a/libcxx/include/__algorithm/ranges_remove_copy.h b/libcxx/include/__algorithm/ranges_remove_copy.h
index 16e9009e7ef0..210222866759 100644
--- a/libcxx/include/__algorithm/ranges_remove_copy.h
+++ b/libcxx/include/__algorithm/ranges_remove_copy.h
@@ -10,26 +10,23 @@
#define _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H
#include <__algorithm/in_out_result.h>
-#include <__algorithm/make_projected.h>
-#include <__algorithm/remove_copy.h>
+#include <__algorithm/ranges_remove_copy_if.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
-#include <__iterator/iterator_traits.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
-#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -40,32 +37,30 @@ using remove_copy_result = in_out_result<_InIter, _OutIter>;
namespace __remove_copy {
-struct __fn {
-
- template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter, class _Type,
- class _Proj = identity>
- requires indirectly_copyable<_InIter, _OutIter> &&
- indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
- remove_copy_result<_InIter, _OutIter>
- operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result; (void)__value; (void)__proj;
- return {};
- }
-
- template <input_range _Range, weakly_incrementable _OutIter, class _Type, class _Proj = identity>
- requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
- indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*>
- _LIBCPP_HIDE_FROM_ABI constexpr
- remove_copy_result<borrowed_iterator_t<_Range>, _OutIter>
- operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__result; (void)__value; (void)__proj;
- return {};
- }
-
-};
+ struct __fn {
+ template <input_iterator _InIter,
+ sentinel_for<_InIter> _Sent,
+ weakly_incrementable _OutIter,
+ class _Type,
+ class _Proj = identity>
+ requires indirectly_copyable<_InIter, _OutIter> &&
+ indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _Type*>
+ _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type& __value, _Proj __proj = {}) const {
+ auto __pred = [&](auto&& __val) { return __value == __val; };
+ return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
+ }
+
+ template <input_range _Range, weakly_incrementable _OutIter, class _Type, class _Proj = identity>
+ requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
+ indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type*>
+ _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_result<borrowed_iterator_t<_Range>, _OutIter>
+ operator()(_Range&& __range, _OutIter __result, const _Type& __value, _Proj __proj = {}) const {
+ auto __pred = [&](auto&& __val) { return __value == __val; };
+ return ranges::__remove_copy_if_impl(
+ ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj);
+ }
+ };
} // namespace __remove_copy
@@ -76,6 +71,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_remove_copy_if.h b/libcxx/include/__algorithm/ranges_remove_copy_if.h
index 4eafe425b8e3..4fc67454b926 100644
--- a/libcxx/include/__algorithm/ranges_remove_copy_if.h
+++ b/libcxx/include/__algorithm/ranges_remove_copy_if.h
@@ -29,7 +29,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -38,33 +38,43 @@ namespace ranges {
template <class _InIter, class _OutIter>
using remove_copy_if_result = in_out_result<_InIter, _OutIter>;
-namespace __remove_copy_if {
-
-struct __fn {
-
- template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter,
- class _Proj = identity, indirect_unary_predicate<projected<_InIter, _Proj>> _Pred>
- requires indirectly_copyable<_InIter, _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr
- remove_copy_if_result<_InIter, _OutIter>
- operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result; (void)__pred; (void)__proj;
- return {};
+template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
+_LIBCPP_HIDE_FROM_ABI constexpr in_out_result<_InIter, _OutIter>
+__remove_copy_if_impl(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
+ for (; __first != __last; ++__first) {
+ if (!std::invoke(__pred, std::invoke(__proj, *__first))) {
+ *__result = *__first;
+ ++__result;
+ }
}
+ return {std::move(__first), std::move(__result)};
+}
- template <input_range _Range, weakly_incrementable _OutIter, class _Proj = identity,
- indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- requires indirectly_copyable<iterator_t<_Range>, _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr
- remove_copy_if_result<borrowed_iterator_t<_Range>, _OutIter>
- operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__result; (void)__pred; (void)__proj;
- return {};
- }
+namespace __remove_copy_if {
-};
+ struct __fn {
+ template <input_iterator _InIter,
+ sentinel_for<_InIter> _Sent,
+ weakly_incrementable _OutIter,
+ class _Proj = identity,
+ indirect_unary_predicate<projected<_InIter, _Proj>> _Pred>
+ requires indirectly_copyable<_InIter, _OutIter>
+ _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<_InIter, _OutIter>
+ operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
+ return ranges::__remove_copy_if_impl(std::move(__first), std::move(__last), std::move(__result), __pred, __proj);
+ }
+
+ template <input_range _Range,
+ weakly_incrementable _OutIter,
+ class _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _OutIter>
+ _LIBCPP_HIDE_FROM_ABI constexpr remove_copy_if_result<borrowed_iterator_t<_Range>, _OutIter>
+ operator()(_Range&& __range, _OutIter __result, _Pred __pred, _Proj __proj = {}) const {
+ return ranges::__remove_copy_if_impl(
+ ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __proj);
+ }
+ };
} // namespace __remove_copy_if
@@ -75,6 +85,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_COPY_IF_H
diff --git a/libcxx/include/__algorithm/ranges_remove_if.h b/libcxx/include/__algorithm/ranges_remove_if.h
index d4e382e551c6..1f17467fc43e 100644
--- a/libcxx/include/__algorithm/ranges_remove_if.h
+++ b/libcxx/include/__algorithm/ranges_remove_if.h
@@ -27,7 +27,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -56,7 +56,7 @@ struct __fn {
template <permutable _Iter, sentinel_for<_Iter> _Sent,
class _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
return ranges::__remove_if_impl(std::move(__first), std::move(__last), __pred, __proj);
}
@@ -65,7 +65,7 @@ struct __fn {
class _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
requires permutable<iterator_t<_Range>>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
return ranges::__remove_if_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
}
@@ -80,6 +80,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REMOVE_IF_H
diff --git a/libcxx/include/__algorithm/ranges_replace.h b/libcxx/include/__algorithm/ranges_replace.h
index 5e74c3ff80cb..8b12beacb715 100644
--- a/libcxx/include/__algorithm/ranges_replace.h
+++ b/libcxx/include/__algorithm/ranges_replace.h
@@ -24,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined (_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -69,6 +69,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined (_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_H
diff --git a/libcxx/include/__algorithm/ranges_replace_copy.h b/libcxx/include/__algorithm/ranges_replace_copy.h
index 19ef635d6f15..f87a236fbd0d 100644
--- a/libcxx/include/__algorithm/ranges_replace_copy.h
+++ b/libcxx/include/__algorithm/ranges_replace_copy.h
@@ -10,26 +10,23 @@
#define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H
#include <__algorithm/in_out_result.h>
-#include <__algorithm/make_projected.h>
-#include <__algorithm/replace_copy.h>
+#include <__algorithm/ranges_replace_copy_if.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
-#include <__iterator/iterator_traits.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
-#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -40,35 +37,45 @@ using replace_copy_result = in_out_result<_InIter, _OutIter>;
namespace __replace_copy {
-struct __fn {
-
- template <input_iterator _InIter, sentinel_for<_InIter> _Sent, class _Type1, class _Type2,
- output_iterator<const _Type2&> _OutIter, class _Proj = identity>
- requires indirectly_copyable<_InIter, _OutIter> &&
- indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _Type1*>
- _LIBCPP_HIDE_FROM_ABI constexpr
- replace_copy_result<_InIter, _OutIter>
- operator()(_InIter __first, _Sent __last, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value,
+ struct __fn {
+ template <input_iterator _InIter,
+ sentinel_for<_InIter> _Sent,
+ class _OldType,
+ class _NewType,
+ output_iterator<const _NewType&> _OutIter,
+ class _Proj = identity>
+ requires indirectly_copyable<_InIter, _OutIter> &&
+ indirect_binary_predicate<ranges::equal_to, projected<_InIter, _Proj>, const _OldType*>
+ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<_InIter, _OutIter>
+ operator()(_InIter __first,
+ _Sent __last,
+ _OutIter __result,
+ const _OldType& __old_value,
+ const _NewType& __new_value,
_Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result; (void)__old_value; (void)__new_value; (void)__proj;
- return {};
- }
-
- template <input_range _Range, class _Type1, class _Type2, output_iterator<const _Type2&> _OutIter,
- class _Proj = identity>
- requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
- indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Type1*>
- _LIBCPP_HIDE_FROM_ABI constexpr
- replace_copy_result<borrowed_iterator_t<_Range>, _OutIter>
- operator()(_Range&& __range, _OutIter __result, const _Type1& __old_value, const _Type2& __new_value,
+ auto __pred = [&](const auto& __value) { return __value == __old_value; };
+ return ranges::__replace_copy_if_impl(
+ std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj);
+ }
+
+ template <input_range _Range,
+ class _OldType,
+ class _NewType,
+ output_iterator<const _NewType&> _OutIter,
+ class _Proj = identity>
+ requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
+ indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _OldType*>
+ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_result<borrowed_iterator_t<_Range>, _OutIter>
+ operator()(_Range&& __range,
+ _OutIter __result,
+ const _OldType& __old_value,
+ const _NewType& __new_value,
_Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__result; (void)__old_value; (void)__new_value; (void)__proj;
- return {};
- }
-
-};
+ auto __pred = [&](const auto& __value) { return __value == __old_value; };
+ return ranges::__replace_copy_if_impl(
+ ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj);
+ }
+ };
} // namespace __replace_copy
@@ -79,6 +86,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_replace_copy_if.h b/libcxx/include/__algorithm/ranges_replace_copy_if.h
index 2a908e2057af..b8741ec7be5e 100644
--- a/libcxx/include/__algorithm/ranges_replace_copy_if.h
+++ b/libcxx/include/__algorithm/ranges_replace_copy_if.h
@@ -10,26 +10,21 @@
#define _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H
#include <__algorithm/in_out_result.h>
-#include <__algorithm/make_projected.h>
-#include <__algorithm/replace_copy_if.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
-#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
-#include <__iterator/iterator_traits.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
-#include <__utility/forward.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -38,34 +33,51 @@ namespace ranges {
template <class _InIter, class _OutIter>
using replace_copy_if_result = in_out_result<_InIter, _OutIter>;
-namespace __replace_copy_if {
-
-struct __fn {
-
- template <input_iterator _InIter, sentinel_for<_InIter> _Sent, class _Type, output_iterator<const _Type&> _OutIter,
- class _Proj = identity, indirect_unary_predicate<projected<_InIter, _Proj>> _Pred>
- requires indirectly_copyable<_InIter, _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr
- replace_copy_if_result<_InIter, _OutIter>
- operator()(_InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value,
- _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result; (void)__pred; (void)__new_value; (void)__proj;
- return {};
+template <class _InIter, class _Sent, class _OutIter, class _Pred, class _Type, class _Proj>
+_LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> __replace_copy_if_impl(
+ _InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, const _Type& __new_value, _Proj& __proj) {
+ while (__first != __last) {
+ if (std::invoke(__pred, std::invoke(__proj, *__first)))
+ *__result = __new_value;
+ else
+ *__result = *__first;
+
+ ++__first;
+ ++__result;
}
- template <input_range _Range, class _Type, output_iterator<const _Type&> _OutIter, class _Proj = identity,
- indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
- requires indirectly_copyable<iterator_t<_Range>, _OutIter>
- _LIBCPP_HIDE_FROM_ABI constexpr
- replace_copy_if_result<borrowed_iterator_t<_Range>, _OutIter>
- operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__result; (void)__pred; (void)__new_value; (void)__proj;
- return {};
- }
+ return {std::move(__first), std::move(__result)};
+}
+
+namespace __replace_copy_if {
-};
+ struct __fn {
+ template <input_iterator _InIter,
+ sentinel_for<_InIter> _Sent,
+ class _Type,
+ output_iterator<const _Type&> _OutIter,
+ class _Proj = identity,
+ indirect_unary_predicate<projected<_InIter, _Proj>> _Pred>
+ requires indirectly_copyable<_InIter, _OutIter>
+ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<_InIter, _OutIter> operator()(
+ _InIter __first, _Sent __last, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {})
+ const {
+ return ranges::__replace_copy_if_impl(
+ std::move(__first), std::move(__last), std::move(__result), __pred, __new_value, __proj);
+ }
+
+ template <input_range _Range,
+ class _Type,
+ output_iterator<const _Type&> _OutIter,
+ class _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
+ requires indirectly_copyable<iterator_t<_Range>, _OutIter>
+ _LIBCPP_HIDE_FROM_ABI constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _OutIter>
+ operator()(_Range&& __range, _OutIter __result, _Pred __pred, const _Type& __new_value, _Proj __proj = {}) const {
+ return ranges::__replace_copy_if_impl(
+ ranges::begin(__range), ranges::end(__range), std::move(__result), __pred, __new_value, __proj);
+ }
+ };
} // namespace __replace_copy_if
@@ -76,6 +88,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_COPY_IF_H
diff --git a/libcxx/include/__algorithm/ranges_replace_if.h b/libcxx/include/__algorithm/ranges_replace_if.h
index 0f9555fc35c2..65be3c7d76d5 100644
--- a/libcxx/include/__algorithm/ranges_replace_if.h
+++ b/libcxx/include/__algorithm/ranges_replace_if.h
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined (_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -72,6 +72,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined (_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REPLACE_IF_H
diff --git a/libcxx/include/__algorithm/ranges_reverse.h b/libcxx/include/__algorithm/ranges_reverse.h
index e7555d0f9acd..e2a5d9a8250d 100644
--- a/libcxx/include/__algorithm/ranges_reverse.h
+++ b/libcxx/include/__algorithm/ranges_reverse.h
@@ -22,7 +22,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -78,6 +78,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_H
diff --git a/libcxx/include/__algorithm/ranges_reverse_copy.h b/libcxx/include/__algorithm/ranges_reverse_copy.h
index e2da9b484aaf..a84b1ad78050 100644
--- a/libcxx/include/__algorithm/ranges_reverse_copy.h
+++ b/libcxx/include/__algorithm/ranges_reverse_copy.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -62,6 +62,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_REVERSE_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_rotate.h b/libcxx/include/__algorithm/ranges_rotate.h
new file mode 100644
index 000000000000..91ed4027df2b
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_rotate.h
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_ROTATE_H
+#define _LIBCPP___ALGORITHM_RANGES_ROTATE_H
+
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/ranges_iterator_concept.h>
+#include <__algorithm/rotate.h>
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/permutable.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/subrange.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+namespace __rotate {
+
+struct __fn {
+
+ template <class _Iter, class _Sent>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ static subrange<_Iter> __rotate_fn_impl(_Iter __first, _Iter __middle, _Sent __last) {
+ auto __ret = std::__rotate<_RangeAlgPolicy>(
+ std::move(__first), std::move(__middle), std::move(__last));
+ return {std::move(__ret.first), std::move(__ret.second)};
+ }
+
+ template <permutable _Iter, sentinel_for<_Iter> _Sent>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ subrange<_Iter> operator()(_Iter __first, _Iter __middle, _Sent __last) const {
+ return __rotate_fn_impl(std::move(__first), std::move(__middle), std::move(__last));
+ }
+
+ template <forward_range _Range>
+ requires permutable<iterator_t<_Range>>
+ _LIBCPP_HIDE_FROM_ABI constexpr
+ borrowed_subrange_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle) const {
+ return __rotate_fn_impl(ranges::begin(__range), std::move(__middle), ranges::end(__range));
+ }
+
+};
+
+} // namespace __rotate
+
+inline namespace __cpo {
+ inline constexpr auto rotate = __rotate::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_H
diff --git a/libcxx/include/__algorithm/ranges_rotate_copy.h b/libcxx/include/__algorithm/ranges_rotate_copy.h
index d7a282c86750..52f403c16a80 100644
--- a/libcxx/include/__algorithm/ranges_rotate_copy.h
+++ b/libcxx/include/__algorithm/ranges_rotate_copy.h
@@ -23,7 +23,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -63,6 +63,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_ROTATE_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_sample.h b/libcxx/include/__algorithm/ranges_sample.h
new file mode 100644
index 000000000000..a37cb64fa2bf
--- /dev/null
+++ b/libcxx/include/__algorithm/ranges_sample.h
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_SAMPLE_H
+#define _LIBCPP___ALGORITHM_RANGES_SAMPLE_H
+
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/sample.h>
+#include <__algorithm/uniform_random_bit_generator_adaptor.h>
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__random/uniform_random_bit_generator.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+namespace __sample {
+
+struct __fn {
+
+ template <input_iterator _Iter, sentinel_for<_Iter> _Sent, weakly_incrementable _OutIter, class _Gen>
+ requires (forward_iterator<_Iter> || random_access_iterator<_OutIter>) &&
+ indirectly_copyable<_Iter, _OutIter> &&
+ uniform_random_bit_generator<remove_reference_t<_Gen>>
+ _LIBCPP_HIDE_FROM_ABI
+ _OutIter operator()(_Iter __first, _Sent __last,
+ _OutIter __out_first, iter_difference_t<_Iter> __n, _Gen&& __gen) const {
+ _ClassicGenAdaptor<_Gen> __adapted_gen(__gen);
+ return std::__sample<_RangeAlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__out_first), __n, __adapted_gen);
+ }
+
+ template <input_range _Range, weakly_incrementable _OutIter, class _Gen>
+ requires (forward_range<_Range> || random_access_iterator<_OutIter>) &&
+ indirectly_copyable<iterator_t<_Range>, _OutIter> &&
+ uniform_random_bit_generator<remove_reference_t<_Gen>>
+ _LIBCPP_HIDE_FROM_ABI
+ _OutIter operator()(_Range&& __range, _OutIter __out_first, range_difference_t<_Range> __n, _Gen&& __gen) const {
+ return (*this)(ranges::begin(__range), ranges::end(__range),
+ std::move(__out_first), __n, std::forward<_Gen>(__gen));
+ }
+
+};
+
+} // namespace __sample
+
+inline namespace __cpo {
+ inline constexpr auto sample = __sample::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_SAMPLE_H
diff --git a/libcxx/include/__algorithm/ranges_search.h b/libcxx/include/__algorithm/ranges_search.h
index 0564bbe1f8b3..388d5afa499d 100644
--- a/libcxx/include/__algorithm/ranges_search.h
+++ b/libcxx/include/__algorithm/ranges_search.h
@@ -22,12 +22,13 @@
#include <__ranges/concepts.h>
#include <__ranges/size.h>
#include <__ranges/subrange.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -74,7 +75,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred __pred = {},
@@ -89,7 +90,7 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range1> operator()(_Range1&& __range1,
_Range2&& __range2,
_Pred __pred = {},
@@ -129,6 +130,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_H
diff --git a/libcxx/include/__algorithm/ranges_search_n.h b/libcxx/include/__algorithm/ranges_search_n.h
index 29fdbfb1c725..56ec8f33d431 100644
--- a/libcxx/include/__algorithm/ranges_search_n.h
+++ b/libcxx/include/__algorithm/ranges_search_n.h
@@ -25,12 +25,13 @@
#include <__ranges/size.h>
#include <__ranges/subrange.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -52,12 +53,8 @@ struct __fn {
}
if constexpr (random_access_iterator<_Iter1>) {
- auto __ret = __search_n_random_access_impl<_RangeAlgPolicy>(__first, __last,
- __count,
- __value,
- __pred,
- __proj,
- __size);
+ auto __ret = std::__search_n_random_access_impl<_RangeAlgPolicy>(
+ __first, __last, __count, __value, __pred, __proj, __size);
return {std::move(__ret.first), std::move(__ret.second)};
}
}
@@ -75,7 +72,7 @@ struct __fn {
class _Pred = ranges::equal_to,
class _Proj = identity>
requires indirectly_comparable<_Iter, const _Type*, _Pred, _Proj>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
subrange<_Iter> operator()(_Iter __first, _Sent __last,
iter_difference_t<_Iter> __count,
const _Type& __value,
@@ -86,7 +83,7 @@ struct __fn {
template <forward_range _Range, class _Type, class _Pred = ranges::equal_to, class _Proj = identity>
requires indirectly_comparable<iterator_t<_Range>, const _Type*, _Pred, _Proj>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_subrange_t<_Range> operator()(_Range&& __range,
range_difference_t<_Range> __count,
const _Type& __value,
@@ -115,6 +112,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SEARCH_N_H
diff --git a/libcxx/include/__algorithm/ranges_set_difference.h b/libcxx/include/__algorithm/ranges_set_difference.h
index 4eb3efad3895..607dd687a5de 100644
--- a/libcxx/include/__algorithm/ranges_set_difference.h
+++ b/libcxx/include/__algorithm/ranges_set_difference.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/set_difference.h>
#include <__config>
@@ -23,12 +24,13 @@
#include <__ranges/dangling.h>
#include <__type_traits/decay.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -59,7 +61,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_difference(
+ auto __ret = std::__set_difference<_RangeAlgPolicy>(
__first1, __last1, __first2, __last2, __result, ranges::__make_projected_comp(__comp, __proj1, __proj2));
return {std::move(__ret.first), std::move(__ret.second)};
}
@@ -71,7 +73,7 @@ struct __fn {
class _Comp = less,
class _Proj1 = identity,
class _Proj2 = identity>
- requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2>
+ requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr set_difference_result<borrowed_iterator_t<_Range1>, _OutIter>
operator()(
_Range1&& __range1,
@@ -80,7 +82,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_difference(
+ auto __ret = std::__set_difference<_RangeAlgPolicy>(
ranges::begin(__range1),
ranges::end(__range1),
ranges::begin(__range2),
@@ -100,5 +102,5 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H
diff --git a/libcxx/include/__algorithm/ranges_set_intersection.h b/libcxx/include/__algorithm/ranges_set_intersection.h
index 05af91ae29e5..aa9fd24ced09 100644
--- a/libcxx/include/__algorithm/ranges_set_intersection.h
+++ b/libcxx/include/__algorithm/ranges_set_intersection.h
@@ -28,7 +28,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -82,7 +82,7 @@ struct __fn {
_OutIter,
_Comp,
_Proj1,
- _Proj2>
+ _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr set_intersection_result<borrowed_iterator_t<_Range1>,
borrowed_iterator_t<_Range2>,
_OutIter>
@@ -113,5 +113,5 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SET_INTERSECTION_H
diff --git a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h
index c54cf3a65112..bc4a9065503b 100644
--- a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h
+++ b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H
#include <__algorithm/in_in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/set_symmetric_difference.h>
#include <__config>
@@ -27,7 +28,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -58,7 +59,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_symmetric_difference(
+ auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>(
std::move(__first1),
std::move(__last1),
std::move(__first2),
@@ -81,7 +82,7 @@ struct __fn {
_OutIter,
_Comp,
_Proj1,
- _Proj2>
+ _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<borrowed_iterator_t<_Range1>,
borrowed_iterator_t<_Range2>,
_OutIter>
@@ -92,7 +93,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_symmetric_difference(
+ auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>(
ranges::begin(__range1),
ranges::end(__range1),
ranges::begin(__range2),
@@ -112,5 +113,5 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H
diff --git a/libcxx/include/__algorithm/ranges_set_union.h b/libcxx/include/__algorithm/ranges_set_union.h
index 3826e55688f7..f8cd45ca0e33 100644
--- a/libcxx/include/__algorithm/ranges_set_union.h
+++ b/libcxx/include/__algorithm/ranges_set_union.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_SET_UNION_H
#include <__algorithm/in_in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/set_union.h>
#include <__config>
@@ -30,7 +31,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -61,7 +62,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_union(
+ auto __ret = std::__set_union<_RangeAlgPolicy>(
std::move(__first1),
std::move(__last1),
std::move(__first2),
@@ -84,7 +85,7 @@ struct __fn {
_OutIter,
_Comp,
_Proj1,
- _Proj2>
+ _Proj2>
_LIBCPP_HIDE_FROM_ABI constexpr set_union_result<borrowed_iterator_t<_Range1>,
borrowed_iterator_t<_Range2>,
_OutIter>
@@ -95,7 +96,7 @@ struct __fn {
_Comp __comp = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
- auto __ret = std::__set_union(
+ auto __ret = std::__set_union<_RangeAlgPolicy>(
ranges::begin(__range1),
ranges::end(__range1),
ranges::begin(__range2),
@@ -115,6 +116,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SET_UNION_H
diff --git a/libcxx/include/__algorithm/ranges_shuffle.h b/libcxx/include/__algorithm/ranges_shuffle.h
index b101a8582eac..a2f2c0edded6 100644
--- a/libcxx/include/__algorithm/ranges_shuffle.h
+++ b/libcxx/include/__algorithm/ranges_shuffle.h
@@ -11,6 +11,7 @@
#include <__algorithm/iterator_operations.h>
#include <__algorithm/shuffle.h>
+#include <__algorithm/uniform_random_bit_generator_adaptor.h>
#include <__config>
#include <__functional/invoke.h>
#include <__functional/ranges_operations.h>
@@ -30,10 +31,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -41,34 +39,6 @@ namespace ranges {
namespace __shuffle {
struct __fn {
- // `std::shuffle` is more constrained than `std::ranges::shuffle`. `std::ranges::shuffle` only requires the given
- // generator to satisfy the `std::uniform_random_bit_generator` concept. `std::shuffle` requires the given
- // generator to meet the uniform random bit generator requirements; these requirements include satisfying
- // `std::uniform_random_bit_generator` and add a requirement for the generator to provide a nested `result_type`
- // typedef (see `[rand.req.urng]`).
- //
- // To reuse the implementation from `std::shuffle`, make the given generator meet the classic requirements by wrapping
- // it into an adaptor type that forwards all of its interface and adds the required typedef.
- template <class _Gen>
- class _ClassicGenAdaptor {
- private:
- // The generator is not required to be copyable or movable, so it has to be stored as a reference.
- _Gen& __gen;
-
- public:
- using result_type = invoke_result_t<_Gen&>;
-
- _LIBCPP_HIDE_FROM_ABI
- static constexpr auto min() { return __uncvref_t<_Gen>::min(); }
- _LIBCPP_HIDE_FROM_ABI
- static constexpr auto max() { return __uncvref_t<_Gen>::max(); }
-
- _LIBCPP_HIDE_FROM_ABI
- constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {}
-
- _LIBCPP_HIDE_FROM_ABI
- constexpr auto operator()() const { return __gen(); }
- };
template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Gen>
requires permutable<_Iter> && uniform_random_bit_generator<remove_reference_t<_Gen>>
@@ -96,8 +66,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-_LIBCPP_POP_MACROS
-
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H
diff --git a/libcxx/include/__algorithm/ranges_sort.h b/libcxx/include/__algorithm/ranges_sort.h
index ef14db64295d..32391df5f6d9 100644
--- a/libcxx/include/__algorithm/ranges_sort.h
+++ b/libcxx/include/__algorithm/ranges_sort.h
@@ -31,7 +31,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -44,7 +44,7 @@ struct __fn {
_Iter __sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
return __last_iter;
@@ -74,6 +74,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SORT_H
diff --git a/libcxx/include/__algorithm/ranges_sort_heap.h b/libcxx/include/__algorithm/ranges_sort_heap.h
index eb6a30dcd3d0..9feb0f609b25 100644
--- a/libcxx/include/__algorithm/ranges_sort_heap.h
+++ b/libcxx/include/__algorithm/ranges_sort_heap.h
@@ -32,7 +32,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -45,7 +45,7 @@ struct __fn {
_Iter __sort_heap_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__sort_heap<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
return __last_iter;
@@ -75,6 +75,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SORT_HEAP_H
diff --git a/libcxx/include/__algorithm/ranges_stable_partition.h b/libcxx/include/__algorithm/ranges_stable_partition.h
index 27957db8829f..c3469f17c7d7 100644
--- a/libcxx/include/__algorithm/ranges_stable_partition.h
+++ b/libcxx/include/__algorithm/ranges_stable_partition.h
@@ -34,7 +34,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -45,11 +45,11 @@ struct __fn {
template <class _Iter, class _Sent, class _Proj, class _Pred>
_LIBCPP_HIDE_FROM_ABI static
- subrange<__uncvref_t<_Iter>> __stable_partition_fn_impl(
+ subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl(
_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_pred = ranges::__make_projected_pred(__pred, __proj);
+ auto&& __projected_pred = std::__make_projected(__pred, __proj);
auto __result = std::__stable_partition<_RangeAlgPolicy>(
std::move(__first), __last_iter, __projected_pred, __iterator_concept<_Iter>());
@@ -83,6 +83,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_STABLE_PARTITION_H
diff --git a/libcxx/include/__algorithm/ranges_stable_sort.h b/libcxx/include/__algorithm/ranges_stable_sort.h
index de48416a41be..d3c48ddb9b8e 100644
--- a/libcxx/include/__algorithm/ranges_stable_sort.h
+++ b/libcxx/include/__algorithm/ranges_stable_sort.h
@@ -31,7 +31,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -44,7 +44,7 @@ struct __fn {
static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
auto __last_iter = ranges::next(__first, __last);
- auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
+ auto&& __projected_comp = std::__make_projected(__comp, __proj);
std::__stable_sort_impl<_RangeAlgPolicy>(std::move(__first), __last_iter, __projected_comp);
return __last_iter;
@@ -74,6 +74,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_STABLE_SORT_H
diff --git a/libcxx/include/__algorithm/ranges_swap_ranges.h b/libcxx/include/__algorithm/ranges_swap_ranges.h
index 3254e1c60abb..552fd55ff88f 100644
--- a/libcxx/include/__algorithm/ranges_swap_ranges.h
+++ b/libcxx/include/__algorithm/ranges_swap_ranges.h
@@ -10,6 +10,8 @@
#define _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H
#include <__algorithm/in_in_result.h>
+#include <__algorithm/iterator_operations.h>
+#include <__algorithm/swap_ranges.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/iter_swap.h>
@@ -22,7 +24,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -38,12 +40,9 @@ struct __fn {
requires indirectly_swappable<_I1, _I2>
_LIBCPP_HIDE_FROM_ABI constexpr swap_ranges_result<_I1, _I2>
operator()(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2) const {
- while (__first1 != __last1 && __first2 != __last2) {
- ranges::iter_swap(__first1, __first2);
- ++__first1;
- ++__first2;
- }
- return {_VSTD::move(__first1), _VSTD::move(__first2)};
+ auto __ret = std::__swap_ranges<_RangeAlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2));
+ return {std::move(__ret.first), std::move(__ret.second)};
}
template <input_range _R1, input_range _R2>
@@ -64,6 +63,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_SWAP_RANGES_H
diff --git a/libcxx/include/__algorithm/ranges_transform.h b/libcxx/include/__algorithm/ranges_transform.h
index 3c13b1b79ff3..c0981a04a9bb 100644
--- a/libcxx/include/__algorithm/ranges_transform.h
+++ b/libcxx/include/__algorithm/ranges_transform.h
@@ -26,7 +26,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -165,6 +165,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H
diff --git a/libcxx/include/__algorithm/ranges_unique.h b/libcxx/include/__algorithm/ranges_unique.h
index bdf755e9406e..be427ccf7fad 100644
--- a/libcxx/include/__algorithm/ranges_unique.h
+++ b/libcxx/include/__algorithm/ranges_unique.h
@@ -9,6 +9,7 @@
#ifndef _LIBCPP___ALGORITHM_RANGES_UNIQUE_H
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_H
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique.h>
#include <__config>
@@ -25,40 +26,44 @@
#include <__ranges/subrange.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __unique {
-struct __fn {
+ struct __fn {
+ template <
+ permutable _Iter,
+ sentinel_for<_Iter> _Sent,
+ class _Proj = identity,
+ indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr subrange<_Iter>
+ operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __ret = std::__unique<_RangeAlgPolicy>(
+ std::move(__first), std::move(__last), std::__make_projected(__comp, __proj));
+ return {std::move(__ret.first), std::move(__ret.second)};
+ }
- template <permutable _Iter, sentinel_for<_Iter> _Sent, class _Proj = identity,
- indirect_equivalence_relation<projected<_Iter, _Proj>> _Comp = ranges::equal_to>
- _LIBCPP_HIDE_FROM_ABI constexpr
- subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__comp; (void)__proj;
- return {};
- }
-
- template <forward_range _Range, class _Proj = identity,
- indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
- requires permutable<iterator_t<_Range>>
- _LIBCPP_HIDE_FROM_ABI constexpr
- borrowed_subrange_t<_Range> operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__comp; (void)__proj;
- return {};
- }
-
-};
+ template <
+ forward_range _Range,
+ class _Proj = identity,
+ indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
+ requires permutable<iterator_t<_Range>>
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range>
+ operator()(_Range&& __range, _Comp __comp = {}, _Proj __proj = {}) const {
+ auto __ret = std::__unique<_RangeAlgPolicy>(
+ ranges::begin(__range), ranges::end(__range), std::__make_projected(__comp, __proj));
+ return {std::move(__ret.first), std::move(__ret.second)};
+ }
+ };
} // namespace __unique
@@ -69,6 +74,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_H
diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h
index 56361aa8ae2f..3ad47b06f5db 100644
--- a/libcxx/include/__algorithm/ranges_unique_copy.h
+++ b/libcxx/include/__algorithm/ranges_unique_copy.h
@@ -10,6 +10,7 @@
#define _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H
#include <__algorithm/in_out_result.h>
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/make_projected.h>
#include <__algorithm/unique_copy.h>
#include <__concepts/same_as.h>
@@ -19,19 +20,20 @@
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
-#include <__iterator/readable_traits.h>
#include <__iterator/projected.h>
+#include <__iterator/readable_traits.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
#include <__ranges/dangling.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -42,47 +44,73 @@ using unique_copy_result = in_out_result<_InIter, _OutIter>;
namespace __unique_copy {
+template <class _InIter, class _OutIter>
+concept __can_reread_from_output = (input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>);
+
struct __fn {
+ template <class _InIter, class _OutIter>
+ static consteval auto __get_algo_tag() {
+ if constexpr (forward_iterator<_InIter>) {
+ return __unique_copy_tags::__reread_from_input_tag{};
+ } else if constexpr (__can_reread_from_output<_InIter, _OutIter>) {
+ return __unique_copy_tags::__reread_from_output_tag{};
+ } else if constexpr (indirectly_copyable_storable<_InIter, _OutIter>) {
+ return __unique_copy_tags::__read_from_tmp_value_tag{};
+ }
+ }
+
+ template <class _InIter, class _OutIter>
+ using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>());
- template <input_iterator _InIter, sentinel_for<_InIter> _Sent, weakly_incrementable _OutIter, class _Proj = identity,
+ template <input_iterator _InIter,
+ sentinel_for<_InIter> _Sent,
+ weakly_incrementable _OutIter,
+ class _Proj = identity,
indirect_equivalence_relation<projected<_InIter, _Proj>> _Comp = ranges::equal_to>
- requires indirectly_copyable<_InIter, _OutIter> &&
- (forward_iterator<_InIter> ||
- (input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
- indirectly_copyable_storable<_InIter, _OutIter>)
- _LIBCPP_HIDE_FROM_ABI constexpr
- unique_copy_result<_InIter, _OutIter>
+ requires indirectly_copyable<_InIter, _OutIter> &&
+ (forward_iterator<_InIter> ||
+ (input_iterator<_OutIter> && same_as<iter_value_t<_InIter>, iter_value_t<_OutIter>>) ||
+ indirectly_copyable_storable<_InIter, _OutIter>)
+ _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<_InIter, _OutIter>
operator()(_InIter __first, _Sent __last, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__first; (void)__last; (void)__result; (void)__comp; (void)__proj;
- return {};
+ auto __ret = std::__unique_copy<_RangeAlgPolicy>(
+ std::move(__first),
+ std::move(__last),
+ std::move(__result),
+ std::__make_projected(__comp, __proj),
+ __algo_tag_t<_InIter, _OutIter>());
+ return {std::move(__ret.first), std::move(__ret.second)};
}
- template <input_range _Range, weakly_incrementable _OutIter, class _Proj = identity,
+ template <input_range _Range,
+ weakly_incrementable _OutIter,
+ class _Proj = identity,
indirect_equivalence_relation<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to>
- requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
- (forward_iterator<iterator_t<_Range>> ||
- (input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
- indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
- _LIBCPP_HIDE_FROM_ABI constexpr
- unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
+ requires indirectly_copyable<iterator_t<_Range>, _OutIter> &&
+ (forward_iterator<iterator_t<_Range>> ||
+ (input_iterator<_OutIter> && same_as<range_value_t<_Range>, iter_value_t<_OutIter>>) ||
+ indirectly_copyable_storable<iterator_t<_Range>, _OutIter>)
+ _LIBCPP_HIDE_FROM_ABI constexpr unique_copy_result<borrowed_iterator_t<_Range>, _OutIter>
operator()(_Range&& __range, _OutIter __result, _Comp __comp = {}, _Proj __proj = {}) const {
- // TODO: implement
- (void)__range; (void)__result; (void)__comp; (void)__proj;
- return {};
+ auto __ret = std::__unique_copy<_RangeAlgPolicy>(
+ ranges::begin(__range),
+ ranges::end(__range),
+ std::move(__result),
+ std::__make_projected(__comp, __proj),
+ __algo_tag_t<iterator_t<_Range>, _OutIter>());
+ return {std::move(__ret.first), std::move(__ret.second)};
}
-
};
} // namespace __unique_copy
inline namespace __cpo {
- inline constexpr auto unique_copy = __unique_copy::__fn{};
+inline constexpr auto unique_copy = __unique_copy::__fn{};
} // namespace __cpo
} // namespace ranges
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_UNIQUE_COPY_H
diff --git a/libcxx/include/__algorithm/ranges_upper_bound.h b/libcxx/include/__algorithm/ranges_upper_bound.h
index 3c63249248fa..a1340809048c 100644
--- a/libcxx/include/__algorithm/ranges_upper_bound.h
+++ b/libcxx/include/__algorithm/ranges_upper_bound.h
@@ -25,7 +25,7 @@
# pragma GCC system_header
#endif
-#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#if _LIBCPP_STD_VER > 17
_LIBCPP_BEGIN_NAMESPACE_STD
@@ -34,7 +34,7 @@ namespace __upper_bound {
struct __fn {
template <forward_iterator _Iter, sentinel_for<_Iter> _Sent, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<_Iter, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
_Iter operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __comp_lhs_rhs_swapped = [&](const auto& __lhs, const auto& __rhs) {
return !std::invoke(__comp, __rhs, __lhs);
@@ -45,7 +45,7 @@ struct __fn {
template <forward_range _Range, class _Type, class _Proj = identity,
indirect_strict_weak_order<const _Type*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less>
- _LIBCPP_HIDE_FROM_ABI constexpr
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
borrowed_iterator_t<_Range> operator()(_Range&& __r,
const _Type& __value,
_Comp __comp = {},
@@ -70,6 +70,6 @@ inline namespace __cpo {
_LIBCPP_END_NAMESPACE_STD
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
+#endif // _LIBCPP_STD_VER > 17
#endif // _LIBCPP___ALGORITHM_RANGES_UPPER_BOUND_H
diff --git a/libcxx/include/__algorithm/remove.h b/libcxx/include/__algorithm/remove.h
index 8a7e99ba09a1..533e41b54fa4 100644
--- a/libcxx/include/__algorithm/remove.h
+++ b/libcxx/include/__algorithm/remove.h
@@ -21,7 +21,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
{
__first = _VSTD::find(__first, __last, __value);
diff --git a/libcxx/include/__algorithm/remove_copy.h b/libcxx/include/__algorithm/remove_copy.h
index 55fc1d90a1e7..ecba08a053e6 100644
--- a/libcxx/include/__algorithm/remove_copy.h
+++ b/libcxx/include/__algorithm/remove_copy.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
remove_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, const _Tp& __value)
{
diff --git a/libcxx/include/__algorithm/remove_copy_if.h b/libcxx/include/__algorithm/remove_copy_if.h
index 36ddba4883ab..2f235fd32ff6 100644
--- a/libcxx/include/__algorithm/remove_copy_if.h
+++ b/libcxx/include/__algorithm/remove_copy_if.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
remove_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _Predicate __pred)
{
diff --git a/libcxx/include/__algorithm/remove_if.h b/libcxx/include/__algorithm/remove_if.h
index 0ae131498d22..27350728d256 100644
--- a/libcxx/include/__algorithm/remove_if.h
+++ b/libcxx/include/__algorithm/remove_if.h
@@ -20,7 +20,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Predicate>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
remove_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred)
{
__first = _VSTD::find_if<_ForwardIterator, _Predicate&>(__first, __last, __pred);
diff --git a/libcxx/include/__algorithm/replace.h b/libcxx/include/__algorithm/replace.h
index d0ae8f65d4a2..ce6215066f51 100644
--- a/libcxx/include/__algorithm/replace.h
+++ b/libcxx/include/__algorithm/replace.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
replace(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_value, const _Tp& __new_value)
{
diff --git a/libcxx/include/__algorithm/replace_copy.h b/libcxx/include/__algorithm/replace_copy.h
index 7c8a5a0b93cb..bebb14cbe210 100644
--- a/libcxx/include/__algorithm/replace_copy.h
+++ b/libcxx/include/__algorithm/replace_copy.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
replace_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
const _Tp& __old_value, const _Tp& __new_value)
diff --git a/libcxx/include/__algorithm/replace_copy_if.h b/libcxx/include/__algorithm/replace_copy_if.h
index 9d8a68fdc0f3..e1ddb527be84 100644
--- a/libcxx/include/__algorithm/replace_copy_if.h
+++ b/libcxx/include/__algorithm/replace_copy_if.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator, class _Predicate, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
replace_copy_if(_InputIterator __first, _InputIterator __last, _OutputIterator __result,
_Predicate __pred, const _Tp& __new_value)
diff --git a/libcxx/include/__algorithm/replace_if.h b/libcxx/include/__algorithm/replace_if.h
index 37c719a34c84..b3a3367d2233 100644
--- a/libcxx/include/__algorithm/replace_if.h
+++ b/libcxx/include/__algorithm/replace_if.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _Predicate, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, const _Tp& __new_value)
{
diff --git a/libcxx/include/__algorithm/reverse.h b/libcxx/include/__algorithm/reverse.h
index 0202cd740833..aa76951707a3 100644
--- a/libcxx/include/__algorithm/reverse.h
+++ b/libcxx/include/__algorithm/reverse.h
@@ -10,8 +10,10 @@
#define _LIBCPP___ALGORITHM_REVERSE_H
#include <__algorithm/iter_swap.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -19,36 +21,43 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _BidirectionalIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+template <class _AlgPolicy, class _BidirectionalIterator>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
-__reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag)
+__reverse_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, bidirectional_iterator_tag)
{
while (__first != __last)
{
if (__first == --__last)
break;
- _VSTD::iter_swap(__first, __last);
+ _IterOps<_AlgPolicy>::iter_swap(__first, __last);
++__first;
}
}
-template <class _RandomAccessIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+template <class _AlgPolicy, class _RandomAccessIterator>
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
-__reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag)
+__reverse_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, random_access_iterator_tag)
{
if (__first != __last)
for (; __first < --__last; ++__first)
- _VSTD::iter_swap(__first, __last);
+ _IterOps<_AlgPolicy>::iter_swap(__first, __last);
+}
+
+template <class _AlgPolicy, class _BidirectionalIterator, class _Sentinel>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+void __reverse(_BidirectionalIterator __first, _Sentinel __last) {
+ using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_BidirectionalIterator>;
+ std::__reverse_impl<_AlgPolicy>(std::move(__first), std::move(__last), _IterCategory());
}
template <class _BidirectionalIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
void
reverse(_BidirectionalIterator __first, _BidirectionalIterator __last)
{
- _VSTD::__reverse(__first, __last, typename iterator_traits<_BidirectionalIterator>::iterator_category());
+ std::__reverse<_ClassicAlgPolicy>(std::move(__first), std::move(__last));
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/reverse_copy.h b/libcxx/include/__algorithm/reverse_copy.h
index 158390707803..f4a0e9713dd5 100644
--- a/libcxx/include/__algorithm/reverse_copy.h
+++ b/libcxx/include/__algorithm/reverse_copy.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _BidirectionalIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result)
{
diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h
index fcf8444a65a0..8934ce095bbc 100644
--- a/libcxx/include/__algorithm/rotate.h
+++ b/libcxx/include/__algorithm/rotate.h
@@ -15,10 +15,8 @@
#include <__algorithm/swap_ranges.h>
#include <__config>
#include <__iterator/iterator_traits.h>
-#include <__iterator/next.h>
-#include <__iterator/prev.h>
#include <__utility/move.h>
-#include <__utility/swap.h>
+#include <__utility/pair.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -28,33 +26,35 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _ForwardIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
__rotate_left(_ForwardIterator __first, _ForwardIterator __last)
{
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
- value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__first);
- // TODO(ranges): pass `_AlgPolicy` to `move`.
- _ForwardIterator __lm1 = _VSTD::move(_VSTD::next(__first), __last, __first);
+ using _Ops = _IterOps<_AlgPolicy>;
+
+ value_type __tmp = _Ops::__iter_move(__first);
+ _ForwardIterator __lm1 = std::__move<_AlgPolicy>(
+ _Ops::next(__first), __last, __first).second;
*__lm1 = _VSTD::move(__tmp);
return __lm1;
}
template <class _AlgPolicy, class _BidirectionalIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator
__rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last)
{
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
- // TODO(ranges): pass `_AlgPolicy` to `prev`.
- _BidirectionalIterator __lm1 = _VSTD::prev(__last);
- value_type __tmp = _IterOps<_AlgPolicy>::__iter_move(__lm1);
- // TODO(ranges): pass `_AlgPolicy` to `move_backward`.
- _BidirectionalIterator __fp1 = _VSTD::move_backward(__first, __lm1, __last);
+ using _Ops = _IterOps<_AlgPolicy>;
+
+ _BidirectionalIterator __lm1 = _Ops::prev(__last);
+ value_type __tmp = _Ops::__iter_move(__lm1);
+ _BidirectionalIterator __fp1 = std::__move_backward<_AlgPolicy>(__first, __lm1, std::move(__last)).second;
*__first = _VSTD::move(__tmp);
return __fp1;
}
template <class _AlgPolicy, class _ForwardIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX14 _ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _ForwardIterator
__rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)
{
_ForwardIterator __i = __middle;
@@ -90,7 +90,7 @@ __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIt
template<typename _Integral>
inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_AFTER_CXX14 _Integral
+_LIBCPP_CONSTEXPR_SINCE_CXX17 _Integral
__algo_gcd(_Integral __x, _Integral __y)
{
do
@@ -103,31 +103,31 @@ __algo_gcd(_Integral __x, _Integral __y)
}
template <class _AlgPolicy, typename _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX14 _RandomAccessIterator
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _RandomAccessIterator
__rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
+ using _Ops = _IterOps<_AlgPolicy>;
const difference_type __m1 = __middle - __first;
- const difference_type __m2 = __last - __middle;
+ const difference_type __m2 = _Ops::distance(__middle, __last);
if (__m1 == __m2)
{
- // TODO(ranges): pass `_AlgPolicy` to `swap_ranges`.
- _VSTD::swap_ranges(__first, __middle, __middle);
+ std::__swap_ranges<_AlgPolicy>(__first, __middle, __middle, __last);
return __middle;
}
const difference_type __g = _VSTD::__algo_gcd(__m1, __m2);
for (_RandomAccessIterator __p = __first + __g; __p != __first;)
{
- value_type __t(_IterOps<_AlgPolicy>::__iter_move(--__p));
+ value_type __t(_Ops::__iter_move(--__p));
_RandomAccessIterator __p1 = __p;
_RandomAccessIterator __p2 = __p1 + __m1;
do
{
- *__p1 = _IterOps<_AlgPolicy>::__iter_move(__p2);
+ *__p1 = _Ops::__iter_move(__p2);
__p1 = __p2;
- const difference_type __d = __last - __p2;
+ const difference_type __d = _Ops::distance(__p2, __last);
if (__m1 < __d)
__p2 += __m1;
else
@@ -140,7 +140,7 @@ __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ran
template <class _AlgPolicy, class _ForwardIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _ForwardIterator
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
__rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last,
_VSTD::forward_iterator_tag)
{
@@ -155,7 +155,7 @@ __rotate_impl(_ForwardIterator __first, _ForwardIterator __middle, _ForwardItera
template <class _AlgPolicy, class _BidirectionalIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _BidirectionalIterator
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _BidirectionalIterator
__rotate_impl(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last,
bidirectional_iterator_tag)
{
@@ -172,7 +172,7 @@ __rotate_impl(_BidirectionalIterator __first, _BidirectionalIterator __middle, _
template <class _AlgPolicy, class _RandomAccessIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator
+_LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator
__rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last,
random_access_iterator_tag)
{
@@ -188,25 +188,32 @@ __rotate_impl(_RandomAccessIterator __first, _RandomAccessIterator __middle, _Ra
return std::__rotate_forward<_AlgPolicy>(__first, __middle, __last);
}
-template <class _AlgPolicy, class _RandomAccessIterator, class _IterCategory>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-_RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle,
- _RandomAccessIterator __last, _IterCategory __iter_category) {
+template <class _AlgPolicy, class _Iterator, class _Sentinel>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+pair<_Iterator, _Iterator>
+__rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) {
+ using _Ret = pair<_Iterator, _Iterator>;
+ _Iterator __last_iter = _IterOps<_AlgPolicy>::next(__middle, __last);
+
if (__first == __middle)
- return __last;
+ return _Ret(__last_iter, __last_iter);
if (__middle == __last)
- return __first;
+ return _Ret(std::move(__first), std::move(__last_iter));
+
+ using _IterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_Iterator>;
+ auto __result = std::__rotate_impl<_AlgPolicy>(
+ std::move(__first), std::move(__middle), __last_iter, _IterCategory());
- return std::__rotate_impl<_AlgPolicy>(std::move(__first), std::move(__middle), std::move(__last), __iter_category);
+ return _Ret(std::move(__result), std::move(__last_iter));
}
template <class _ForwardIterator>
inline _LIBCPP_INLINE_VISIBILITY
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last)
{
- return std::__rotate<_ClassicAlgPolicy>(__first, __middle, __last,
- typename iterator_traits<_ForwardIterator>::iterator_category());
+ return std::__rotate<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__middle), std::move(__last)).first;
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/rotate_copy.h b/libcxx/include/__algorithm/rotate_copy.h
index ab569ef7c6be..c154649ab98c 100644
--- a/libcxx/include/__algorithm/rotate_copy.h
+++ b/libcxx/include/__algorithm/rotate_copy.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _OutputIterator __result)
{
diff --git a/libcxx/include/__algorithm/sample.h b/libcxx/include/__algorithm/sample.h
index e04466a08d5a..f403ba612580 100644
--- a/libcxx/include/__algorithm/sample.h
+++ b/libcxx/include/__algorithm/sample.h
@@ -9,12 +9,14 @@
#ifndef _LIBCPP___ALGORITHM_SAMPLE_H
#define _LIBCPP___ALGORITHM_SAMPLE_H
+#include <__algorithm/iterator_operations.h>
#include <__algorithm/min.h>
#include <__assert>
#include <__config>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__random/uniform_int_distribution.h>
+#include <__utility/move.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -26,13 +28,14 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _PopulationIterator, class _SampleIterator, class _Distance,
+template <class _AlgPolicy,
+ class _PopulationIterator, class _PopulationSentinel, class _SampleIterator, class _Distance,
class _UniformRandomNumberGenerator>
_LIBCPP_INLINE_VISIBILITY
_SampleIterator __sample(_PopulationIterator __first,
- _PopulationIterator __last, _SampleIterator __output_iter,
+ _PopulationSentinel __last, _SampleIterator __output_iter,
_Distance __n,
- _UniformRandomNumberGenerator & __g,
+ _UniformRandomNumberGenerator& __g,
input_iterator_tag) {
_Distance __k = 0;
@@ -47,15 +50,16 @@ _SampleIterator __sample(_PopulationIterator __first,
return __output_iter + _VSTD::min(__n, __k);
}
-template <class _PopulationIterator, class _SampleIterator, class _Distance,
+template <class _AlgPolicy,
+ class _PopulationIterator, class _PopulationSentinel, class _SampleIterator, class _Distance,
class _UniformRandomNumberGenerator>
_LIBCPP_INLINE_VISIBILITY
_SampleIterator __sample(_PopulationIterator __first,
- _PopulationIterator __last, _SampleIterator __output_iter,
+ _PopulationSentinel __last, _SampleIterator __output_iter,
_Distance __n,
_UniformRandomNumberGenerator& __g,
forward_iterator_tag) {
- _Distance __unsampled_sz = _VSTD::distance(__first, __last);
+ _Distance __unsampled_sz = _IterOps<_AlgPolicy>::distance(__first, __last);
for (__n = _VSTD::min(__n, __unsampled_sz); __n != 0; ++__first) {
_Distance __r = uniform_int_distribution<_Distance>(0, --__unsampled_sz)(__g);
if (__r < __n) {
@@ -66,24 +70,22 @@ _SampleIterator __sample(_PopulationIterator __first,
return __output_iter;
}
-template <class _PopulationIterator, class _SampleIterator, class _Distance,
+template <class _AlgPolicy,
+ class _PopulationIterator, class _PopulationSentinel, class _SampleIterator, class _Distance,
class _UniformRandomNumberGenerator>
_LIBCPP_INLINE_VISIBILITY
_SampleIterator __sample(_PopulationIterator __first,
- _PopulationIterator __last, _SampleIterator __output_iter,
+ _PopulationSentinel __last, _SampleIterator __output_iter,
_Distance __n, _UniformRandomNumberGenerator& __g) {
- typedef typename iterator_traits<_PopulationIterator>::iterator_category
- _PopCategory;
- typedef typename iterator_traits<_PopulationIterator>::difference_type
- _Difference;
- static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value ||
- __is_cpp17_random_access_iterator<_SampleIterator>::value,
- "SampleIterator must meet the requirements of RandomAccessIterator");
- typedef typename common_type<_Distance, _Difference>::type _CommonType;
_LIBCPP_ASSERT(__n >= 0, "N must be a positive number.");
- return _VSTD::__sample(
- __first, __last, __output_iter, _CommonType(__n),
- __g, _PopCategory());
+
+ using _PopIterCategory = typename _IterOps<_AlgPolicy>::template __iterator_category<_PopulationIterator>;
+ using _Difference = typename _IterOps<_AlgPolicy>::template __difference_type<_PopulationIterator>;
+ using _CommonType = typename common_type<_Distance, _Difference>::type;
+
+ return std::__sample<_AlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__output_iter), _CommonType(__n),
+ __g, _PopIterCategory());
}
#if _LIBCPP_STD_VER > 14
@@ -93,8 +95,14 @@ inline _LIBCPP_INLINE_VISIBILITY
_SampleIterator sample(_PopulationIterator __first,
_PopulationIterator __last, _SampleIterator __output_iter,
_Distance __n, _UniformRandomNumberGenerator&& __g) {
- return _VSTD::__sample(__first, __last, __output_iter, __n, __g);
+ static_assert(__is_cpp17_forward_iterator<_PopulationIterator>::value ||
+ __is_cpp17_random_access_iterator<_SampleIterator>::value,
+ "SampleIterator must meet the requirements of RandomAccessIterator");
+
+ return std::__sample<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__output_iter), __n, __g);
}
+
#endif // _LIBCPP_STD_VER > 14
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h
index 4ead6cac82b7..93771be39e35 100644
--- a/libcxx/include/__algorithm/search.h
+++ b/libcxx/include/__algorithm/search.h
@@ -33,7 +33,7 @@ template <class _AlgPolicy,
class _Pred,
class _Proj1,
class _Proj2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter1, _Iter1> __search_forward_impl(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred& __pred,
@@ -80,7 +80,7 @@ template <class _AlgPolicy,
class _Proj2,
class _DiffT1,
class _DiffT2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter1, _Iter1> __search_random_access_impl(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred& __pred,
@@ -120,7 +120,7 @@ template <class _Iter1, class _Sent1,
class _Pred,
class _Proj1,
class _Proj2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred& __pred,
@@ -152,7 +152,7 @@ template <class _Iter1, class _Sent1,
class _Pred,
class _Proj1,
class _Proj2>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1,
_Iter2 __first2, _Sent2 __last2,
_Pred& __pred,
@@ -170,7 +170,7 @@ pair<_Iter1, _Iter1> __search_impl(_Iter1 __first1, _Sent1 __last1,
}
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2,
_BinaryPredicate __pred) {
@@ -181,17 +181,15 @@ _ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
}
template <class _ForwardIterator1, class _ForwardIterator2>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator1 search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_ForwardIterator2 __first2, _ForwardIterator2 __last2) {
- using __v1 = typename iterator_traits<_ForwardIterator1>::value_type;
- using __v2 = typename iterator_traits<_ForwardIterator2>::value_type;
- return std::search(__first1, __last1, __first2, __last2, __equal_to<__v1, __v2>());
+ return std::search(__first1, __last1, __first2, __last2, __equal_to());
}
#if _LIBCPP_STD_VER > 14
template <class _ForwardIterator, class _Searcher>
-_LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
search(_ForwardIterator __f, _ForwardIterator __l, const _Searcher& __s) {
return __s(__f, __l).first;
}
diff --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h
index ccb8e845f5b1..60a073565156 100644
--- a/libcxx/include/__algorithm/search_n.h
+++ b/libcxx/include/__algorithm/search_n.h
@@ -19,6 +19,7 @@
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__ranges/concepts.h>
+#include <__utility/convert_to_integral.h>
#include <__utility/pair.h>
#include <type_traits> // __convert_to_integral
@@ -29,7 +30,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Pred, class _Iter, class _Sent, class _SizeT, class _Type, class _Proj>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter, _Iter> __search_n_forward_impl(_Iter __first, _Sent __last,
_SizeT __count,
const _Type& __value,
@@ -71,7 +72,7 @@ pair<_Iter, _Iter> __search_n_forward_impl(_Iter __first, _Sent __last,
}
template <class _AlgPolicy, class _Pred, class _Iter, class _Sent, class _SizeT, class _Type, class _Proj, class _DiffT>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
std::pair<_Iter, _Iter> __search_n_random_access_impl(_Iter __first, _Sent __last,
_SizeT __count,
const _Type& __value,
@@ -122,7 +123,7 @@ template <class _Iter, class _Sent,
class _Type,
class _Pred,
class _Proj>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter, _Iter> __search_n_impl(_Iter __first, _Sent __last,
_DiffT __count,
const _Type& __value,
@@ -142,7 +143,7 @@ template <class _Iter1, class _Sent1,
class _Type,
class _Pred,
class _Proj>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
pair<_Iter1, _Iter1> __search_n_impl(_Iter1 __first, _Sent1 __last,
_DiffT __count,
const _Type& __value,
@@ -158,7 +159,7 @@ pair<_Iter1, _Iter1> __search_n_impl(_Iter1 __first, _Sent1 __last,
}
template <class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last,
_Size __count,
const _Tp& __value,
@@ -170,10 +171,9 @@ _ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last,
}
template <class _ForwardIterator, class _Size, class _Tp>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_ForwardIterator search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value) {
- typedef typename iterator_traits<_ForwardIterator>::value_type __v;
- return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to<__v, _Tp>());
+ return std::search_n(__first, __last, std::__convert_to_integral(__count), __value, __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/set_difference.h b/libcxx/include/__algorithm/set_difference.h
index 4378bd5304d9..cffdc8fc4fc0 100644
--- a/libcxx/include/__algorithm/set_difference.h
+++ b/libcxx/include/__algorithm/set_difference.h
@@ -12,6 +12,7 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/copy.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__functional/identity.h>
#include <__functional/invoke.h>
@@ -26,8 +27,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template < class _Comp, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<__uncvref_t<_InIter1>, __uncvref_t<_OutIter> >
+template <class _AlgPolicy, class _Comp, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__remove_cvref_t<_InIter1>, __remove_cvref_t<_OutIter> >
__set_difference(
_InIter1&& __first1, _Sent1&& __last1, _InIter2&& __first2, _Sent2&& __last2, _OutIter&& __result, _Comp&& __comp) {
while (__first1 != __last1 && __first2 != __last2) {
@@ -42,29 +43,30 @@ __set_difference(
++__first2;
}
}
- return std::__copy(std::move(__first1), std::move(__last1), std::move(__result));
+ return std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result));
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_difference(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_difference(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_OutputIterator __result,
_Compare __comp) {
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__set_difference<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp).second;
+ return std::__set_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >(
+ __first1, __last1, __first2, __last2, __result, __comp)
+ .second;
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_difference(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_difference(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_OutputIterator __result) {
- return std::__set_difference(
+ return std::__set_difference<_ClassicAlgPolicy>(
__first1,
__last1,
__first2,
diff --git a/libcxx/include/__algorithm/set_intersection.h b/libcxx/include/__algorithm/set_intersection.h
index 77cc83738d1f..9fa7799aee62 100644
--- a/libcxx/include/__algorithm/set_intersection.h
+++ b/libcxx/include/__algorithm/set_intersection.h
@@ -30,13 +30,13 @@ struct __set_intersection_result {
_OutIter __out_;
// need a constructor as C++03 aggregate init is hard
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
__set_intersection_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter)
: __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {}
};
template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 __set_intersection_result<_InIter1, _InIter2, _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_intersection_result<_InIter1, _InIter2, _OutIter>
__set_intersection(
_InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) {
while (__first1 != __last1 && __first2 != __last2) {
@@ -59,15 +59,14 @@ __set_intersection(
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_intersection(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_intersection(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_OutputIterator __result,
_Compare __comp) {
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__set_intersection<_ClassicAlgPolicy, _Comp_ref>(
+ return std::__set_intersection<_ClassicAlgPolicy, __comp_ref_type<_Compare> >(
std::move(__first1),
std::move(__last1),
std::move(__first2),
@@ -78,7 +77,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_i
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_intersection(
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_intersection(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
diff --git a/libcxx/include/__algorithm/set_symmetric_difference.h b/libcxx/include/__algorithm/set_symmetric_difference.h
index cd532ab5800d..bcb09587032b 100644
--- a/libcxx/include/__algorithm/set_symmetric_difference.h
+++ b/libcxx/include/__algorithm/set_symmetric_difference.h
@@ -12,9 +12,11 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/copy.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -29,18 +31,18 @@ struct __set_symmetric_difference_result {
_OutIter __out_;
// need a constructor as C++03 aggregate init is hard
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
__set_symmetric_difference_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter)
: __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {}
};
-template <class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>
+template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>
__set_symmetric_difference(
_InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) {
while (__first1 != __last1) {
if (__first2 == __last2) {
- auto __ret1 = std::__copy_impl(std::move(__first1), std::move(__last1), std::move(__result));
+ auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result));
return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>(
std::move(__ret1.first), std::move(__first2), std::move((__ret1.second)));
}
@@ -58,21 +60,20 @@ __set_symmetric_difference(
++__first2;
}
}
- auto __ret2 = std::__copy_impl(std::move(__first2), std::move(__last2), std::move(__result));
+ auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result));
return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>(
std::move(__first1), std::move(__ret2.first), std::move((__ret2.second)));
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_symmetric_difference(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetric_difference(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_OutputIterator __result,
_Compare __comp) {
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__set_symmetric_difference<_Comp_ref>(
+ return std::__set_symmetric_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >(
std::move(__first1),
std::move(__last1),
std::move(__first2),
@@ -83,7 +84,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_symmetri
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_symmetric_difference(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetric_difference(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
diff --git a/libcxx/include/__algorithm/set_union.h b/libcxx/include/__algorithm/set_union.h
index 3bd437980161..4d154b81e092 100644
--- a/libcxx/include/__algorithm/set_union.h
+++ b/libcxx/include/__algorithm/set_union.h
@@ -12,9 +12,11 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/copy.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -29,17 +31,17 @@ struct __set_union_result {
_OutIter __out_;
// need a constructor as C++03 aggregate init is hard
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
__set_union_result(_InIter1&& __in_iter1, _InIter2&& __in_iter2, _OutIter&& __out_iter)
: __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {}
};
-template <class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union(
+template <class _AlgPolicy, class _Compare, class _InIter1, class _Sent1, class _InIter2, class _Sent2, class _OutIter>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union(
_InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) {
for (; __first1 != __last1; ++__result) {
if (__first2 == __last2) {
- auto __ret1 = std::__copy_impl(std::move(__first1), std::move(__last1), std::move(__result));
+ auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result));
return __set_union_result<_InIter1, _InIter2, _OutIter>(
std::move(__ret1.first), std::move(__first2), std::move((__ret1.second)));
}
@@ -54,21 +56,20 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 __set_union_result<_InIter1,
++__first1;
}
}
- auto __ret2 = std::__copy_impl(std::move(__first2), std::move(__last2), std::move(__result));
+ auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result));
return __set_union_result<_InIter1, _InIter2, _OutIter>(
std::move(__first1), std::move(__ret2.first), std::move((__ret2.second)));
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _Compare>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_union(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
_InputIterator2 __last2,
_OutputIterator __result,
_Compare __comp) {
- typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
- return std::__set_union<_Comp_ref>(
+ return std::__set_union<_ClassicAlgPolicy, __comp_ref_type<_Compare> >(
std::move(__first1),
std::move(__last1),
std::move(__first2),
@@ -79,7 +80,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_union(
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_union(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
diff --git a/libcxx/include/__algorithm/shuffle.h b/libcxx/include/__algorithm/shuffle.h
index e32c6a7608ba..f7bce68697b5 100644
--- a/libcxx/include/__algorithm/shuffle.h
+++ b/libcxx/include/__algorithm/shuffle.h
@@ -16,6 +16,7 @@
#include <__random/uniform_int_distribution.h>
#include <__utility/forward.h>
#include <__utility/move.h>
+#include <__utility/swap.h>
#include <cstddef>
#include <cstdint>
@@ -31,9 +32,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
class _LIBCPP_TYPE_VIS __libcpp_debug_randomizer {
public:
__libcpp_debug_randomizer() {
- __state = __seed();
- __inc = __state + 0xda3e39cb94b95bdbULL;
- __inc = (__inc << 1) | 1;
+ __state_ = __seed();
+ __inc_ = __state_ + 0xda3e39cb94b95bdbULL;
+ __inc_ = (__inc_ << 1) | 1;
}
typedef uint_fast32_t result_type;
@@ -41,8 +42,8 @@ public:
static const result_type _Max = 0xFFFFFFFF;
_LIBCPP_HIDE_FROM_ABI result_type operator()() {
- uint_fast64_t __oldstate = __state;
- __state = __oldstate * 6364136223846793005ULL + __inc;
+ uint_fast64_t __oldstate = __state_;
+ __state_ = __oldstate * 6364136223846793005ULL + __inc_;
return __oldstate >> 32;
}
@@ -50,8 +51,8 @@ public:
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR result_type max() { return _Max; }
private:
- uint_fast64_t __state;
- uint_fast64_t __inc;
+ uint_fast64_t __state_;
+ uint_fast64_t __inc_;
_LIBCPP_HIDE_FROM_ABI static uint_fast64_t __seed() {
#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED
return _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED;
@@ -93,7 +94,7 @@ public:
_LIBCPP_FUNC_VIS __rs_default __rs_get();
template <class _RandomAccessIterator>
-_LIBCPP_DEPRECATED_IN_CXX14 void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -114,7 +115,7 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
}
template <class _RandomAccessIterator, class _RandomNumberGenerator>
-_LIBCPP_DEPRECATED_IN_CXX14 void
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX14 void
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
#ifndef _LIBCPP_CXX03_LANG
_RandomNumberGenerator&& __rand)
@@ -137,7 +138,7 @@ random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
#endif
template <class _AlgPolicy, class _RandomAccessIterator, class _Sentinel, class _UniformRandomNumberGenerator>
-_RandomAccessIterator __shuffle(
+_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator __shuffle(
_RandomAccessIterator __first, _Sentinel __last_sentinel, _UniformRandomNumberGenerator&& __g) {
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef uniform_int_distribution<ptrdiff_t> _Dp;
@@ -161,8 +162,8 @@ _RandomAccessIterator __shuffle(
}
template <class _RandomAccessIterator, class _UniformRandomNumberGenerator>
-void shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
- _UniformRandomNumberGenerator&& __g) {
+_LIBCPP_HIDE_FROM_ABI void
+shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, _UniformRandomNumberGenerator&& __g) {
(void)std::__shuffle<_ClassicAlgPolicy>(
std::move(__first), std::move(__last), std::forward<_UniformRandomNumberGenerator>(__g));
}
diff --git a/libcxx/include/__algorithm/sift_down.h b/libcxx/include/__algorithm/sift_down.h
index be2eb29dd53a..e3972fb6f46e 100644
--- a/libcxx/include/__algorithm/sift_down.h
+++ b/libcxx/include/__algorithm/sift_down.h
@@ -22,8 +22,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void
-__sift_down(_RandomAccessIterator __first, _Compare __comp,
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
+__sift_down(_RandomAccessIterator __first, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
_RandomAccessIterator __start)
{
@@ -78,8 +78,8 @@ __sift_down(_RandomAccessIterator __first, _Compare __comp,
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 _RandomAccessIterator
-__floyd_sift_down(_RandomAccessIterator __first, _Compare __comp,
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _RandomAccessIterator
+__floyd_sift_down(_RandomAccessIterator __first, _Compare&& __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len)
{
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h
index 1ca2f1b81712..a7d2d55a06f8 100644
--- a/libcxx/include/__algorithm/sort.h
+++ b/libcxx/include/__algorithm/sort.h
@@ -11,19 +11,29 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
+#include <__algorithm/iter_swap.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min_element.h>
#include <__algorithm/partial_sort.h>
#include <__algorithm/unwrap_iter.h>
-#include <__bits>
+#include <__assert>
+#include <__bit/blsr.h>
+#include <__bit/countl.h>
+#include <__bit/countr.h>
#include <__config>
#include <__debug>
#include <__debug_utils/randomize_range.h>
#include <__functional/operations.h>
#include <__functional/ranges_operations.h>
#include <__iterator/iterator_traits.h>
+#include <__memory/destruct_n.h>
+#include <__memory/unique_ptr.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#include <climits>
-#include <memory>
+#include <cstdint>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -43,7 +53,7 @@ struct _WrapAlgPolicy {
using _Comp = _CompT;
_Comp& __comp;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
_WrapAlgPolicy(_Comp& __c) : __comp(__c) {}
};
@@ -62,7 +72,7 @@ struct _UnwrapAlgPolicy {
using _AlgPolicy = _ClassicAlgPolicy;
using _Comp = _CompT;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
_Comp __get_comp(_Comp __comp) { return __comp; }
};
@@ -73,14 +83,15 @@ struct _UnwrapAlgPolicy<_WrapAlgPolicy<_Ts...> > {
using _AlgPolicy = typename _Wrapped::_AlgPolicy;
using _Comp = typename _Wrapped::_Comp;
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 static
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
_Comp __get_comp(_Wrapped& __w) { return __w.__comp; }
};
// stable, 2-3 compares, 0-2 swaps
template <class _AlgPolicy, class _Compare, class _ForwardIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z,
+_LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX14 unsigned __sort3(_ForwardIterator __x, _ForwardIterator __y, _ForwardIterator __z,
_Compare __c) {
using _Ops = _IterOps<_AlgPolicy>;
@@ -118,10 +129,10 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 unsigned __sort3(_ForwardIterator __x, _ForwardIte
// stable, 3-6 compares, 0-5 swaps
template <class _AlgPolicy, class _Compare, class _ForwardIterator>
+_LIBCPP_HIDE_FROM_ABI
unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4,
_Compare __c) {
- using _Ops = _IterOps<_AlgPolicy>;
-
+ using _Ops = _IterOps<_AlgPolicy>;
unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c);
if (__c(*__x4, *__x3)) {
_Ops::iter_swap(__x3, __x4);
@@ -171,12 +182,12 @@ _LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _F
}
template <class _AlgPolicy, class _Compare, class _ForwardIterator>
-_LIBCPP_HIDDEN unsigned __sort5_wrap_policy(
+_LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy(
_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5,
_Compare __c) {
using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
_WrappedComp __wrapped_comp(__c);
- return std::__sort5<_WrappedComp>(
+ return std::__sort5<_WrappedComp, _ForwardIterator>(
std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp);
}
@@ -201,6 +212,13 @@ using __use_branchless_sort =
integral_constant<bool, __is_cpp17_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) &&
is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>;
+namespace __detail {
+
+// Size in bits for the bitset in use.
+enum { __block_size = sizeof(uint64_t) * 8 };
+
+} // namespace __detail
+
// Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary.
template <class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) {
@@ -231,8 +249,8 @@ template <class, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void>
__sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3,
_Compare __c) {
- _VSTD::__cond_swap<_Compare>(__x2, __x3, __c);
- _VSTD::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c);
+ std::__cond_swap<_Compare>(__x2, __x3, __c);
+ std::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c);
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
@@ -246,11 +264,11 @@ template <class, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void>
__sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3,
_RandomAccessIterator __x4, _Compare __c) {
- _VSTD::__cond_swap<_Compare>(__x1, __x3, __c);
- _VSTD::__cond_swap<_Compare>(__x2, __x4, __c);
- _VSTD::__cond_swap<_Compare>(__x1, __x2, __c);
- _VSTD::__cond_swap<_Compare>(__x3, __x4, __c);
- _VSTD::__cond_swap<_Compare>(__x2, __x3, __c);
+ std::__cond_swap<_Compare>(__x1, __x3, __c);
+ std::__cond_swap<_Compare>(__x2, __x4, __c);
+ std::__cond_swap<_Compare>(__x1, __x2, __c);
+ std::__cond_swap<_Compare>(__x3, __x4, __c);
+ std::__cond_swap<_Compare>(__x2, __x3, __c);
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
@@ -260,16 +278,21 @@ __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2,
std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c);
}
-template <class, class _Compare, class _RandomAccessIterator>
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void>
-__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3,
- _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) {
- _VSTD::__cond_swap<_Compare>(__x1, __x2, __c);
- _VSTD::__cond_swap<_Compare>(__x4, __x5, __c);
- _VSTD::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c);
- _VSTD::__cond_swap<_Compare>(__x2, __x5, __c);
- _VSTD::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c);
- _VSTD::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c);
+__sort5_maybe_branchless(
+ _RandomAccessIterator __x1,
+ _RandomAccessIterator __x2,
+ _RandomAccessIterator __x3,
+ _RandomAccessIterator __x4,
+ _RandomAccessIterator __x5,
+ _Compare __c) {
+ std::__cond_swap<_Compare>(__x1, __x2, __c);
+ std::__cond_swap<_Compare>(__x4, __x5, __c);
+ std::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c);
+ std::__cond_swap<_Compare>(__x2, __x5, __c);
+ std::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c);
+ std::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c);
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
@@ -281,7 +304,8 @@ __sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2,
// Assumes size > 0
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
+_LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX14 void __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
_Compare __comp) {
_BidirectionalIterator __lm1 = __last;
for (--__lm1; __first != __lm1; ++__first) {
@@ -291,32 +315,48 @@ _LIBCPP_CONSTEXPR_AFTER_CXX11 void __selection_sort(_BidirectionalIterator __fir
}
}
+// Sort the iterator range [__first, __last) using the comparator __comp using
+// the insertion sort algorithm.
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
+_LIBCPP_HIDE_FROM_ABI
void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
- if (__first != __last) {
- _BidirectionalIterator __i = __first;
- for (++__i; __i != __last; ++__i) {
- _BidirectionalIterator __j = __i;
- value_type __t(_Ops::__iter_move(__j));
- for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j)
+ if (__first == __last)
+ return;
+ _BidirectionalIterator __i = __first;
+ for (++__i; __i != __last; ++__i) {
+ _BidirectionalIterator __j = __i;
+ --__j;
+ if (__comp(*__i, *__j)) {
+ value_type __t(_Ops::__iter_move(__i));
+ _BidirectionalIterator __k = __j;
+ __j = __i;
+ do {
*__j = _Ops::__iter_move(__k);
- *__j = _VSTD::move(__t);
+ __j = __k;
+ } while (__j != __first && __comp(__t, *--__k));
+ *__j = std::move(__t);
}
}
}
+// Sort the iterator range [__first, __last) using the comparator __comp using
+// the insertion sort algorithm. Insertion sort has two loops, outer and inner.
+// The implementation below has not bounds check (unguarded) for the inner loop.
+// Assumes that there is an element in the position (__first - 1) and that each
+// element in the input range is greater or equal to the element at __first - 1.
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
+_LIBCPP_HIDE_FROM_ABI void
+__insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
-
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
- _RandomAccessIterator __j = __first + difference_type(2);
- std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp);
- for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) {
+ if (__first == __last)
+ return;
+ for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) {
+ _RandomAccessIterator __j = __i - difference_type(1);
if (__comp(*__i, *__j)) {
value_type __t(_Ops::__iter_move(__i));
_RandomAccessIterator __k = __j;
@@ -324,15 +364,14 @@ void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __l
do {
*__j = _Ops::__iter_move(__k);
__j = __k;
- } while (__j != __first && __comp(__t, *--__k));
- *__j = _VSTD::move(__t);
+ } while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above.
+ *__j = std::move(__t);
}
- __j = __i;
}
}
template <class _WrappedComp, class _RandomAccessIterator>
-bool __insertion_sort_incomplete(
+_LIBCPP_HIDDEN bool __insertion_sort_incomplete(
_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) {
using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>;
using _AlgPolicy = typename _Unwrap::_AlgPolicy;
@@ -348,7 +387,7 @@ bool __insertion_sort_incomplete(
return true;
case 2:
if (__comp(*--__last, *__first))
- _IterOps<_AlgPolicy>::iter_swap(__first, __last);
+ _Ops::iter_swap(__first, __last);
return true;
case 3:
std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp);
@@ -377,7 +416,7 @@ bool __insertion_sort_incomplete(
*__j = _Ops::__iter_move(__k);
__j = __k;
} while (__j != __first && __comp(__t, *--__k));
- *__j = _VSTD::move(__t);
+ *__j = std::move(__t);
if (++__count == __limit)
return ++__i == __last;
}
@@ -387,6 +426,7 @@ bool __insertion_sort_incomplete(
}
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
+_LIBCPP_HIDE_FROM_ABI
void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterator __last1,
typename iterator_traits<_BidirectionalIterator>::value_type* __first2, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
@@ -416,17 +456,336 @@ void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterat
}
}
-template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
- typename iterator_traits<_RandomAccessIterator>::difference_type __depth) {
+template <class _AlgPolicy, class _RandomAccessIterator>
+inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
+ _RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) {
+ using _Ops = _IterOps<_AlgPolicy>;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ // Swap one pair on each iteration as long as both bitsets have at least one
+ // element for swapping.
+ while (__left_bitset != 0 && __right_bitset != 0) {
+ difference_type tz_left = __libcpp_ctz(__left_bitset);
+ __left_bitset = __libcpp_blsr(__left_bitset);
+ difference_type tz_right = __libcpp_ctz(__right_bitset);
+ __right_bitset = __libcpp_blsr(__right_bitset);
+ _Ops::iter_swap(__first + tz_left, __last - tz_right);
+ }
+}
+
+template <class _Compare,
+ class _RandomAccessIterator,
+ class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
+inline _LIBCPP_HIDE_FROM_ABI void
+__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) {
+ // Possible vectorization. With a proper "-march" flag, the following loop
+ // will be compiled into a set of SIMD instructions.
+ _RandomAccessIterator __iter = __first;
+ for (int __j = 0; __j < __detail::__block_size;) {
+ bool __comp_result = !__comp(*__iter, __pivot);
+ __left_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
+ __j++;
+ ++__iter;
+ }
+}
+
+template <class _Compare,
+ class _RandomAccessIterator,
+ class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
+inline _LIBCPP_HIDE_FROM_ABI void
+__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) {
+ // Possible vectorization. With a proper "-march" flag, the following loop
+ // will be compiled into a set of SIMD instructions.
+ _RandomAccessIterator __iter = __lm1;
+ for (int __j = 0; __j < __detail::__block_size;) {
+ bool __comp_result = __comp(*__iter, __pivot);
+ __right_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
+ __j++;
+ --__iter;
+ }
+}
+
+template <class _AlgPolicy,
+ class _Compare,
+ class _RandomAccessIterator,
+ class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
+inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
+ _RandomAccessIterator& __first,
+ _RandomAccessIterator& __lm1,
+ _Compare __comp,
+ _ValueType& __pivot,
+ uint64_t& __left_bitset,
+ uint64_t& __right_bitset) {
+ typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ difference_type __remaining_len = __lm1 - __first + 1;
+ difference_type __l_size;
+ difference_type __r_size;
+ if (__left_bitset == 0 && __right_bitset == 0) {
+ __l_size = __remaining_len / 2;
+ __r_size = __remaining_len - __l_size;
+ } else if (__left_bitset == 0) {
+ // We know at least one side is a full block.
+ __l_size = __remaining_len - __detail::__block_size;
+ __r_size = __detail::__block_size;
+ } else { // if (__right_bitset == 0)
+ __l_size = __detail::__block_size;
+ __r_size = __remaining_len - __detail::__block_size;
+ }
+ // Record the comparison outcomes for the elements currently on the left side.
+ if (__left_bitset == 0) {
+ _RandomAccessIterator __iter = __first;
+ for (int j = 0; j < __l_size; j++) {
+ bool __comp_result = !__comp(*__iter, __pivot);
+ __left_bitset |= (static_cast<uint64_t>(__comp_result) << j);
+ ++__iter;
+ }
+ }
+ // Record the comparison outcomes for the elements currently on the right
+ // side.
+ if (__right_bitset == 0) {
+ _RandomAccessIterator __iter = __lm1;
+ for (int j = 0; j < __r_size; j++) {
+ bool __comp_result = __comp(*__iter, __pivot);
+ __right_bitset |= (static_cast<uint64_t>(__comp_result) << j);
+ --__iter;
+ }
+ }
+ std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
+ __first += (__left_bitset == 0) ? __l_size : 0;
+ __lm1 -= (__right_bitset == 0) ? __r_size : 0;
+}
+
+template <class _AlgPolicy, class _RandomAccessIterator>
+inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
+ _RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) {
+ using _Ops = _IterOps<_AlgPolicy>;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ if (__left_bitset) {
+ // Swap within the left side. Need to find set positions in the reverse
+ // order.
+ while (__left_bitset != 0) {
+ difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset);
+ __left_bitset &= (static_cast<uint64_t>(1) << __tz_left) - 1;
+ _RandomAccessIterator it = __first + __tz_left;
+ if (it != __lm1) {
+ _Ops::iter_swap(it, __lm1);
+ }
+ --__lm1;
+ }
+ __first = __lm1 + difference_type(1);
+ } else if (__right_bitset) {
+ // Swap within the right side. Need to find set positions in the reverse
+ // order.
+ while (__right_bitset != 0) {
+ difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset);
+ __right_bitset &= (static_cast<uint64_t>(1) << __tz_right) - 1;
+ _RandomAccessIterator it = __lm1 - __tz_right;
+ if (it != __first) {
+ _Ops::iter_swap(it, __first);
+ }
+ ++__first;
+ }
+ }
+}
+
+// Partition [__first, __last) using the comparator __comp. *__first has the
+// chosen pivot. Elements that are equivalent are kept to the left of the
+// pivot. Returns the iterator for the pivot and a bool value which is true if
+// the provided range is already sorted, false otherwise. We assume that the
+// length of the range is at least three elements.
+//
+// __bitset_partition uses bitsets for storing outcomes of the comparisons
+// between the pivot and other elements.
+template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
+_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
+__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ _LIBCPP_ASSERT(__last - __first >= difference_type(3), "");
+
+ _RandomAccessIterator __begin = __first;
+ value_type __pivot(_Ops::__iter_move(__first));
+ // Find the first element greater than the pivot.
+ if (__comp(__pivot, *(__last - difference_type(1)))) {
+ // Not guarded since we know the last element is greater than the pivot.
+ while (!__comp(__pivot, *++__first)) {
+ }
+ } else {
+ while (++__first < __last && !__comp(__pivot, *__first)) {
+ }
+ }
+ // Find the last element less than or equal to the pivot.
+ if (__first < __last) {
+ // It will be always guarded because __introsort will do the median-of-three
+ // before calling this.
+ while (__comp(__pivot, *--__last)) {
+ }
+ }
+ // If the first element greater than the pivot is at or after the
+ // last element less than or equal to the pivot, then we have covered the
+ // entire range without swapping elements. This implies the range is already
+ // partitioned.
+ bool __already_partitioned = __first >= __last;
+ if (!__already_partitioned) {
+ _Ops::iter_swap(__first, __last);
+ ++__first;
+ }
+
+ // In [__first, __last) __last is not inclusive. From now on, it uses last
+ // minus one to be inclusive on both sides.
+ _RandomAccessIterator __lm1 = __last - difference_type(1);
+ uint64_t __left_bitset = 0;
+ uint64_t __right_bitset = 0;
+
+ // Reminder: length = __lm1 - __first + 1.
+ while (__lm1 - __first >= 2 * __detail::__block_size - 1) {
+ // Record the comparison outcomes for the elements currently on the left
+ // side.
+ if (__left_bitset == 0)
+ std::__populate_left_bitset<_Compare>(__first, __comp, __pivot, __left_bitset);
+ // Record the comparison outcomes for the elements currently on the right
+ // side.
+ if (__right_bitset == 0)
+ std::__populate_right_bitset<_Compare>(__lm1, __comp, __pivot, __right_bitset);
+ // Swap the elements recorded to be the candidates for swapping in the
+ // bitsets.
+ std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
+ // Only advance the iterator if all the elements that need to be moved to
+ // other side were moved.
+ __first += (__left_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
+ __lm1 -= (__right_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
+ }
+ // Now, we have a less-than a block worth of elements on at least one of the
+ // sides.
+ std::__bitset_partition_partial_blocks<_AlgPolicy, _Compare>(
+ __first, __lm1, __comp, __pivot, __left_bitset, __right_bitset);
+ // At least one the bitsets would be empty. For the non-empty one, we need to
+ // properly partition the elements that appear within that bitset.
+ std::__swap_bitmap_pos_within<_AlgPolicy>(__first, __lm1, __left_bitset, __right_bitset);
+
+ // Move the pivot to its correct position.
+ _RandomAccessIterator __pivot_pos = __first - difference_type(1);
+ if (__begin != __pivot_pos) {
+ *__begin = _Ops::__iter_move(__pivot_pos);
+ }
+ *__pivot_pos = std::move(__pivot);
+ return std::make_pair(__pivot_pos, __already_partitioned);
+}
+// Partition [__first, __last) using the comparator __comp. *__first has the
+// chosen pivot. Elements that are equivalent are kept to the right of the
+// pivot. Returns the iterator for the pivot and a bool value which is true if
+// the provided range is already sorted, false otherwise. We assume that the
+// length of the range is at least three elements.
+template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
+_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
+__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
+ using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
- typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
- const difference_type __limit =
- is_trivially_copy_constructible<value_type>::value && is_trivially_copy_assignable<value_type>::value ? 30 : 6;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
+ _LIBCPP_ASSERT(__last - __first >= difference_type(3), "");
+ _RandomAccessIterator __begin = __first;
+ value_type __pivot(_Ops::__iter_move(__first));
+ // Find the first element greater or equal to the pivot. It will be always
+ // guarded because __introsort will do the median-of-three before calling
+ // this.
+ while (__comp(*++__first, __pivot))
+ ;
+
+ // Find the last element less than the pivot.
+ if (__begin == __first - difference_type(1)) {
+ while (__first < __last && !__comp(*--__last, __pivot))
+ ;
+ } else {
+ // Guarded.
+ while (!__comp(*--__last, __pivot))
+ ;
+ }
+
+ // If the first element greater than or equal to the pivot is at or after the
+ // last element less than the pivot, then we have covered the entire range
+ // without swapping elements. This implies the range is already partitioned.
+ bool __already_partitioned = __first >= __last;
+ // Go through the remaining elements. Swap pairs of elements (one to the
+ // right of the pivot and the other to left of the pivot) that are not on the
+ // correct side of the pivot.
+ while (__first < __last) {
+ _Ops::iter_swap(__first, __last);
+ while (__comp(*++__first, __pivot))
+ ;
+ while (!__comp(*--__last, __pivot))
+ ;
+ }
+ // Move the pivot to its correct position.
+ _RandomAccessIterator __pivot_pos = __first - difference_type(1);
+ if (__begin != __pivot_pos) {
+ *__begin = _Ops::__iter_move(__pivot_pos);
+ }
+ *__pivot_pos = std::move(__pivot);
+ return std::make_pair(__pivot_pos, __already_partitioned);
+}
+
+// Similar to the above function. Elements equivalent to the pivot are put to
+// the left of the pivot. Returns the iterator to the pivot element.
+template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
+_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
+__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
+ using _Ops = _IterOps<_AlgPolicy>;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
+ _RandomAccessIterator __begin = __first;
+ value_type __pivot(_Ops::__iter_move(__first));
+ if (__comp(__pivot, *(__last - difference_type(1)))) {
+ // Guarded.
+ while (!__comp(__pivot, *++__first)) {
+ }
+ } else {
+ while (++__first < __last && !__comp(__pivot, *__first)) {
+ }
+ }
+
+ if (__first < __last) {
+ // It will be always guarded because __introsort will do the
+ // median-of-three before calling this.
+ while (__comp(__pivot, *--__last)) {
+ }
+ }
+ while (__first < __last) {
+ _Ops::iter_swap(__first, __last);
+ while (!__comp(__pivot, *++__first))
+ ;
+ while (__comp(__pivot, *--__last))
+ ;
+ }
+ _RandomAccessIterator __pivot_pos = __first - difference_type(1);
+ if (__begin != __pivot_pos) {
+ *__begin = _Ops::__iter_move(__pivot_pos);
+ }
+ *__pivot_pos = std::move(__pivot);
+ return __first;
+}
+
+// The main sorting function. Implements introsort combined with other ideas:
+// - option of using block quick sort for partitioning,
+// - guarded and unguarded insertion sort for small lengths,
+// - Tuckey's ninther technique for computing the pivot,
+// - check on whether partition was not required.
+// The implementation is partly based on Orson Peters' pattern-defeating
+// quicksort, published at: <https://github.com/orlp/pdqsort>.
+template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _UseBitSetPartition>
+void __introsort(_RandomAccessIterator __first,
+ _RandomAccessIterator __last,
+ _Compare __comp,
+ typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
+ bool __leftmost = true) {
+ using _Ops = _IterOps<_AlgPolicy>;
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
+ using _Comp_ref = __comp_ref_type<_Compare>;
+ // Upper bound for using insertion sort for sorting.
+ _LIBCPP_CONSTEXPR difference_type __limit = 24;
+ // Lower bound for using Tuckey's ninther technique for median computation.
+ _LIBCPP_CONSTEXPR difference_type __ninther_threshold = 128;
while (true) {
- __restart:
difference_type __len = __last - __first;
switch (__len) {
case 0:
@@ -434,7 +793,7 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C
return;
case 2:
if (__comp(*--__last, *__first))
- _IterOps<_AlgPolicy>::iter_swap(__first, __last);
+ _Ops::iter_swap(__first, __last);
return;
case 3:
std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp);
@@ -449,127 +808,60 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C
--__last, __comp);
return;
}
- if (__len <= __limit) {
- std::__insertion_sort_3<_AlgPolicy, _Compare>(__first, __last, __comp);
+ // Use insertion sort if the length of the range is below the specified limit.
+ if (__len < __limit) {
+ if (__leftmost) {
+ std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
+ } else {
+ std::__insertion_sort_unguarded<_AlgPolicy, _Compare>(__first, __last, __comp);
+ }
return;
}
- // __len > 5
if (__depth == 0) {
// Fallback to heap sort as Introsort suggests.
std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp);
return;
}
--__depth;
- _RandomAccessIterator __m = __first;
- _RandomAccessIterator __lm1 = __last;
- --__lm1;
- unsigned __n_swaps;
{
- difference_type __delta;
- if (__len >= 1000) {
- __delta = __len / 2;
- __m += __delta;
- __delta /= 2;
- __n_swaps = std::__sort5_wrap_policy<_AlgPolicy, _Compare>(
- __first, __first + __delta, __m, __m + __delta, __lm1, __comp);
+ difference_type __half_len = __len / 2;
+ // Use Tuckey's ninther technique or median of 3 for pivot selection
+ // depending on the length of the range being sorted.
+ if (__len > __ninther_threshold) {
+ std::__sort3<_AlgPolicy, _Compare>(__first, __first + __half_len, __last - difference_type(1), __comp);
+ std::__sort3<_AlgPolicy, _Compare>(
+ __first + difference_type(1), __first + (__half_len - 1), __last - difference_type(2), __comp);
+ std::__sort3<_AlgPolicy, _Compare>(
+ __first + difference_type(2), __first + (__half_len + 1), __last - difference_type(3), __comp);
+ std::__sort3<_AlgPolicy, _Compare>(
+ __first + (__half_len - 1), __first + __half_len, __first + (__half_len + 1), __comp);
+ _Ops::iter_swap(__first, __first + __half_len);
} else {
- __delta = __len / 2;
- __m += __delta;
- __n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, __lm1, __comp);
+ std::__sort3<_AlgPolicy, _Compare>(__first + __half_len, __first, __last - difference_type(1), __comp);
}
}
- // *__m is median
- // partition [__first, __m) < *__m and *__m <= [__m, __last)
- // (this inhibits tossing elements equivalent to __m around unnecessarily)
- _RandomAccessIterator __i = __first;
- _RandomAccessIterator __j = __lm1;
- // j points beyond range to be tested, *__m is known to be <= *__lm1
- // The search going up is known to be guarded but the search coming down isn't.
- // Prime the downward search with a guard.
- if (!__comp(*__i, *__m)) // if *__first == *__m
- {
- // *__first == *__m, *__first doesn't go in first part
- // manually guard downward moving __j against __i
- while (true) {
- if (__i == --__j) {
- // *__first == *__m, *__m <= all other elements
- // Parition instead into [__first, __i) == *__first and *__first < [__i, __last)
- ++__i; // __first + 1
- __j = __last;
- if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1)
- {
- while (true) {
- if (__i == __j)
- return; // [__first, __last) all equivalent elements
- if (__comp(*__first, *__i)) {
- _Ops::iter_swap(__i, __j);
- ++__n_swaps;
- ++__i;
- break;
- }
- ++__i;
- }
- }
- // [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1
- if (__i == __j)
- return;
- while (true) {
- while (!__comp(*__first, *__i))
- ++__i;
- while (__comp(*__first, *--__j))
- ;
- if (__i >= __j)
- break;
- _Ops::iter_swap(__i, __j);
- ++__n_swaps;
- ++__i;
- }
- // [__first, __i) == *__first and *__first < [__i, __last)
- // The first part is sorted, sort the second part
- // _VSTD::__sort<_Compare>(__i, __last, __comp);
- __first = __i;
- goto __restart;
- }
- if (__comp(*__j, *__m)) {
- _Ops::iter_swap(__i, __j);
- ++__n_swaps;
- break; // found guard for downward moving __j, now use unguarded partition
- }
- }
- }
- // It is known that *__i < *__m
- ++__i;
- // j points beyond range to be tested, *__m is known to be <= *__lm1
- // if not yet partitioned...
- if (__i < __j) {
- // known that *(__i - 1) < *__m
- // known that __i <= __m
- while (true) {
- // __m still guards upward moving __i
- while (__comp(*__i, *__m))
- ++__i;
- // It is now known that a guard exists for downward moving __j
- while (!__comp(*--__j, *__m))
- ;
- if (__i > __j)
- break;
- _Ops::iter_swap(__i, __j);
- ++__n_swaps;
- // It is known that __m != __j
- // If __m just moved, follow it
- if (__m == __i)
- __m = __j;
- ++__i;
- }
- }
- // [__first, __i) < *__m and *__m <= [__i, __last)
- if (__i != __m && __comp(*__m, *__i)) {
- _Ops::iter_swap(__i, __m);
- ++__n_swaps;
+ // The elements to the left of the current iterator range are already
+ // sorted. If the current iterator range to be sorted is not the
+ // leftmost part of the entire iterator range and the pivot is same as
+ // the highest element in the range to the left, then we know that all
+ // the elements in the range [first, pivot] would be equal to the pivot,
+ // assuming the equal elements are put on the left side when
+ // partitioned. This also means that we do not need to sort the left
+ // side of the partition.
+ if (!__leftmost && !__comp(*(__first - difference_type(1)), *__first)) {
+ __first = std::__partition_with_equals_on_left<_AlgPolicy, _RandomAccessIterator, _Comp_ref>(
+ __first, __last, _Comp_ref(__comp));
+ continue;
}
+ // Use bitset partition only if asked for.
+ auto __ret =
+ _UseBitSetPartition
+ ? std::__bitset_partition<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp)
+ : std::__partition_with_equals_on_right<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp);
+ _RandomAccessIterator __i = __ret.first;
// [__first, __i) < *__i and *__i <= [__i+1, __last)
// If we were given a perfect partition, see if insertion sort is quick...
- if (__n_swaps == 0) {
+ if (__ret.second) {
using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
_WrappedComp __wrapped_comp(__comp);
bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp);
@@ -585,14 +877,11 @@ void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _C
}
}
}
- // sort smaller range with recursive call and larger with tail recursion elimination
- if (__i - __first < __last - __i) {
- std::__introsort<_AlgPolicy, _Compare>(__first, __i, __comp, __depth);
- __first = ++__i;
- } else {
- std::__introsort<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp, __depth);
- __last = __i;
- }
+ // Sort the left partiton recursively and the right partition with tail recursion elimination.
+ std::__introsort<_AlgPolicy, _Compare, _RandomAccessIterator, _UseBitSetPartition>(
+ __first, __i, __comp, __depth, __leftmost);
+ __leftmost = false;
+ __first = ++__i;
}
}
@@ -616,15 +905,22 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
}
template <class _WrappedComp, class _RandomAccessIterator>
-void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) {
+_LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) {
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
- difference_type __depth_limit = 2 * __log2i(__last - __first);
+ difference_type __depth_limit = 2 * std::__log2i(__last - __first);
using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>;
using _AlgPolicy = typename _Unwrap::_AlgPolicy;
using _Compare = typename _Unwrap::_Comp;
_Compare __comp = _Unwrap::__get_comp(__wrapped_comp);
- std::__introsort<_AlgPolicy, _Compare>(__first, __last, __comp, __depth_limit);
+ // Only use bitset partitioning for arithmetic types. We should also check
+ // that the default comparator is in use so that we are sure that there are no
+ // branches in the comparator.
+ std::__introsort<_AlgPolicy,
+ _Compare,
+ _RandomAccessIterator,
+ __use_branchless_sort<_Compare, _RandomAccessIterator>::value>(
+ __first, __last, __comp, __depth_limit);
}
template <class _Compare, class _Tp>
@@ -672,11 +968,11 @@ extern template _LIBCPP_FUNC_VIS bool __insertion_sort_incomplete<__less<long do
extern template _LIBCPP_FUNC_VIS unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&);
template <class _AlgPolicy, class _RandomAccessIterator, class _Comp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
std::__debug_randomize_range<_AlgPolicy>(__first, __last);
- using _Comp_ref = typename __comp_ref_type<_Comp>::type;
+ using _Comp_ref = __comp_ref_type<_Comp>;
if (__libcpp_is_constant_evaluated()) {
std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp);
@@ -689,13 +985,13 @@ void __sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _C
}
template <class _RandomAccessIterator, class _Comp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
std::__sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::sort(__first, __last, __less<typename iterator_traits<_RandomAccessIterator>::value_type>());
}
diff --git a/libcxx/include/__algorithm/sort_heap.h b/libcxx/include/__algorithm/sort_heap.h
index b9f0b2c9690d..8249407b5509 100644
--- a/libcxx/include/__algorithm/sort_heap.h
+++ b/libcxx/include/__algorithm/sort_heap.h
@@ -25,18 +25,17 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
-void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
- using _CompRef = typename __comp_ref_type<_Compare>::type;
- _CompRef __comp_ref = __comp;
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+void __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare&& __comp) {
+ __comp_ref_type<_Compare> __comp_ref = __comp;
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
for (difference_type __n = __last - __first; __n > 1; --__last, (void) --__n)
- std::__pop_heap<_AlgPolicy, _CompRef>(__first, __last, __comp_ref, __n);
+ std::__pop_heap<_AlgPolicy>(__first, __last, __comp_ref, __n);
}
template <class _RandomAccessIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
static_assert(std::is_copy_constructible<_RandomAccessIterator>::value, "Iterators must be copy constructible.");
static_assert(std::is_copy_assignable<_RandomAccessIterator>::value, "Iterators must be copy assignable.");
@@ -45,7 +44,7 @@ void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, _Com
}
template <class _RandomAccessIterator>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
void sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::sort_heap(std::move(__first), std::move(__last),
__less<typename iterator_traits<_RandomAccessIterator>::value_type>());
diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h
index e5ad48b2ed51..a49de6dbb0ef 100644
--- a/libcxx/include/__algorithm/stable_partition.h
+++ b/libcxx/include/__algorithm/stable_partition.h
@@ -15,7 +15,12 @@
#include <__iterator/advance.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
-#include <memory>
+#include <__memory/destruct_n.h>
+#include <__memory/temporary_buffer.h>
+#include <__memory/unique_ptr.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+#include <new>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -25,7 +30,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
-_ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
_Distance __len, _Pair __p, forward_iterator_tag __fit)
{
@@ -108,13 +113,13 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred
__second_half_done:
// TTTFFFFFTTTTTFFFFF
// f ff m sf l
- return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __fit);
+ return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
// TTTTTTTTFFFFFFFFFF
// |
}
template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
-_ForwardIterator
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred,
forward_iterator_tag)
{
@@ -253,13 +258,13 @@ __first_half_done:
__second_half_done:
// TTTFFFFFTTTTTFFFFF
// f ff m sf l
- return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false, __bit);
+ return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
// TTTTTTTTFFFFFFFFFF
// |
}
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
-_BidirectionalIterator
+_LIBCPP_HIDE_FROM_ABI _BidirectionalIterator
__stable_partition_impl(_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred,
bidirectional_iterator_tag)
{
@@ -305,7 +310,7 @@ template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Ite
_LIBCPP_HIDE_FROM_ABI
_ForwardIterator __stable_partition(
_ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
- return std::__stable_partition_impl<_AlgPolicy, __uncvref_t<_Predicate>&>(
+ return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
std::move(__first), std::move(__last), __pred, __iter_category);
}
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 6122758bdefe..8e70978ab61c 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -16,8 +16,12 @@
#include <__algorithm/sort.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__memory/destruct_n.h>
+#include <__memory/temporary_buffer.h>
+#include <__memory/unique_ptr.h>
#include <__utility/move.h>
-#include <memory>
+#include <__utility/pair.h>
+#include <new>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -27,7 +31,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2>
-void
+_LIBCPP_HIDE_FROM_ABI void
__merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
typename iterator_traits<_InputIterator1>::value_type* __result, _Compare __comp)
@@ -69,7 +73,7 @@ __merge_move_construct(_InputIterator1 __first1, _InputIterator1 __last1,
}
template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
-void
+_LIBCPP_HIDE_FROM_ABI void
__merge_move_assign(_InputIterator1 __first1, _InputIterator1 __last1,
_InputIterator2 __first2, _InputIterator2 __last2,
_OutputIterator __result, _Compare __comp)
@@ -203,7 +207,7 @@ __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp
}
std::__stable_sort<_AlgPolicy, _Compare>(__first, __m, __comp, __l2, __buff, __buff_size);
std::__stable_sort<_AlgPolicy, _Compare>(__m, __last, __comp, __len - __l2, __buff, __buff_size);
- std::__inplace_merge<_AlgPolicy, _Compare>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
+ std::__inplace_merge<_AlgPolicy>(__first, __m, __last, __comp, __l2, __len - __l2, __buff, __buff_size);
}
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
@@ -223,8 +227,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
__h.reset(__buf.first);
}
- using _Comp_ref = typename __comp_ref_type<_Compare>::type;
- std::__stable_sort<_AlgPolicy, _Comp_ref>(__first, __last, __comp, __len, __buf.first, __buf.second);
+ std::__stable_sort<_AlgPolicy, __comp_ref_type<_Compare> >(__first, __last, __comp, __len, __buf.first, __buf.second);
}
template <class _RandomAccessIterator, class _Compare>
diff --git a/libcxx/include/__algorithm/swap_ranges.h b/libcxx/include/__algorithm/swap_ranges.h
index 0422265bb4be..5ce5ed8c8845 100644
--- a/libcxx/include/__algorithm/swap_ranges.h
+++ b/libcxx/include/__algorithm/swap_ranges.h
@@ -9,8 +9,10 @@
#ifndef _LIBCPP___ALGORITHM_SWAP_RANGES_H
#define _LIBCPP___ALGORITHM_SWAP_RANGES_H
+#include <__algorithm/iterator_operations.h>
#include <__config>
-#include <__utility/swap.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -18,12 +20,39 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+// 2+2 iterators: the shorter size will be used.
+template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _Sentinel2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+pair<_ForwardIterator1, _ForwardIterator2>
+__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2, _Sentinel2 __last2) {
+ while (__first1 != __last1 && __first2 != __last2) {
+ _IterOps<_AlgPolicy>::iter_swap(__first1, __first2);
+ ++__first1;
+ ++__first2;
+ }
+
+ return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2));
+}
+
+// 2+1 iterators: size2 >= size1.
+template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+pair<_ForwardIterator1, _ForwardIterator2>
+__swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) {
+ while (__first1 != __last1) {
+ _IterOps<_AlgPolicy>::iter_swap(__first1, __first2);
+ ++__first1;
+ ++__first2;
+ }
+
+ return pair<_ForwardIterator1, _ForwardIterator2>(std::move(__first1), std::move(__first2));
+}
+
template <class _ForwardIterator1, class _ForwardIterator2>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator2
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator2
swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2) {
- for (; __first1 != __last1; ++__first1, (void)++__first2)
- swap(*__first1, *__first2);
- return __first2;
+ return std::__swap_ranges<_ClassicAlgPolicy>(
+ std::move(__first1), std::move(__last1), std::move(__first2)).second;
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/transform.h b/libcxx/include/__algorithm/transform.h
index f9db806f5b94..4722c154cfff 100644
--- a/libcxx/include/__algorithm/transform.h
+++ b/libcxx/include/__algorithm/transform.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _InputIterator, class _OutputIterator, class _UnaryOperation>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
{
@@ -28,7 +28,7 @@ transform(_InputIterator __first, _InputIterator __last, _OutputIterator __resul
}
template <class _InputIterator1, class _InputIterator2, class _OutputIterator, class _BinaryOperation>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_OutputIterator
transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
_OutputIterator __result, _BinaryOperation __binary_op)
diff --git a/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h
new file mode 100644
index 000000000000..1e86074b3dbd
--- /dev/null
+++ b/libcxx/include/__algorithm/uniform_random_bit_generator_adaptor.h
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
+#define _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
+
+#include <__config>
+#include <__functional/invoke.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if _LIBCPP_STD_VER > 17
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// Range versions of random algorithms (e.g. `std::shuffle`) are less constrained than their classic counterparts.
+// Range algorithms only require the given generator to satisfy the `std::uniform_random_bit_generator` concept.
+// Classic algorithms require the given generator to meet the uniform random bit generator requirements; these
+// requirements include satisfying `std::uniform_random_bit_generator` and add a requirement for the generator to
+// provide a nested `result_type` typedef (see `[rand.req.urng]`).
+//
+// To be able to reuse classic implementations, make the given generator meet the classic requirements by wrapping
+// it into an adaptor type that forwards all of its interface and adds the required typedef.
+template <class _Gen>
+class _ClassicGenAdaptor {
+private:
+ // The generator is not required to be copyable or movable, so it has to be stored as a reference.
+ _Gen& __gen_;
+
+public:
+ using result_type = invoke_result_t<_Gen&>;
+
+ _LIBCPP_HIDE_FROM_ABI
+ static constexpr auto min() { return __remove_cvref_t<_Gen>::min(); }
+ _LIBCPP_HIDE_FROM_ABI
+ static constexpr auto max() { return __remove_cvref_t<_Gen>::max(); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen_(__g) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()() const { return __gen_(); }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_STD_VER > 17
+
+#endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
diff --git a/libcxx/include/__algorithm/unique.h b/libcxx/include/__algorithm/unique.h
index 264d727d93c8..1717a00c8a93 100644
--- a/libcxx/include/__algorithm/unique.h
+++ b/libcxx/include/__algorithm/unique.h
@@ -11,9 +11,11 @@
#include <__algorithm/adjacent_find.h>
#include <__algorithm/comp.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -23,32 +25,33 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// unique
+template <class _AlgPolicy, class _Iter, class _Sent, class _BinaryPredicate>
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_Iter, _Iter>
+__unique(_Iter __first, _Sent __last, _BinaryPredicate&& __pred) {
+ __first = std::__adjacent_find(__first, __last, __pred);
+ if (__first != __last) {
+ // ... a a ? ...
+ // f i
+ _Iter __i = __first;
+ for (++__i; ++__i != __last;)
+ if (!__pred(*__first, *__i))
+ *++__first = _IterOps<_AlgPolicy>::__iter_move(__i);
+ ++__first;
+ return std::pair<_Iter, _Iter>(std::move(__first), std::move(__i));
+ }
+ return std::pair<_Iter, _Iter>(__first, __first);
+}
+
template <class _ForwardIterator, class _BinaryPredicate>
-_LIBCPP_NODISCARD_EXT _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
-unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
-{
- __first = _VSTD::adjacent_find<_ForwardIterator, _BinaryPredicate&>(__first, __last, __pred);
- if (__first != __last)
- {
- // ... a a ? ...
- // f i
- _ForwardIterator __i = __first;
- for (++__i; ++__i != __last;)
- if (!__pred(*__first, *__i))
- *++__first = _VSTD::move(*__i);
- ++__first;
- }
- return __first;
+_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
+unique(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred) {
+ return std::__unique<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __pred).first;
}
template <class _ForwardIterator>
-_LIBCPP_NODISCARD_EXT inline
-_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_ForwardIterator
-unique(_ForwardIterator __first, _ForwardIterator __last)
-{
- typedef typename iterator_traits<_ForwardIterator>::value_type __v;
- return _VSTD::unique(__first, __last, __equal_to<__v>());
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
+unique(_ForwardIterator __first, _ForwardIterator __last) {
+ return std::unique(__first, __last, __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/unique_copy.h b/libcxx/include/__algorithm/unique_copy.h
index f58517749f51..81fcd50f011d 100644
--- a/libcxx/include/__algorithm/unique_copy.h
+++ b/libcxx/include/__algorithm/unique_copy.h
@@ -10,8 +10,14 @@
#define _LIBCPP___ALGORITHM_UNIQUE_COPY_H
#include <__algorithm/comp.h>
+#include <__algorithm/iterator_operations.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_base_of.h>
+#include <__type_traits/is_same.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -19,88 +25,98 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _BinaryPredicate, class _InputIterator, class _OutputIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
-__unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred,
- input_iterator_tag, output_iterator_tag)
-{
- if (__first != __last)
- {
- typename iterator_traits<_InputIterator>::value_type __t(*__first);
+namespace __unique_copy_tags {
+
+struct __reread_from_input_tag {};
+struct __reread_from_output_tag {};
+struct __read_from_tmp_value_tag {};
+
+} // namespace __unique_copy_tags
+
+template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _OutputIterator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator>
+__unique_copy(_InputIterator __first,
+ _Sent __last,
+ _OutputIterator __result,
+ _BinaryPredicate&& __pred,
+ __unique_copy_tags::__read_from_tmp_value_tag) {
+ if (__first != __last) {
+ typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first);
+ *__result = __t;
+ ++__result;
+ while (++__first != __last) {
+ if (!__pred(__t, *__first)) {
+ __t = *__first;
*__result = __t;
++__result;
- while (++__first != __last)
- {
- if (!__pred(__t, *__first))
- {
- __t = *__first;
- *__result = __t;
- ++__result;
- }
- }
+ }
}
- return __result;
+ }
+ return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result));
}
-template <class _BinaryPredicate, class _ForwardIterator, class _OutputIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator
-__unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __pred,
- forward_iterator_tag, output_iterator_tag)
-{
- if (__first != __last)
- {
- _ForwardIterator __i = __first;
- *__result = *__i;
+template <class _AlgPolicy, class _BinaryPredicate, class _ForwardIterator, class _Sent, class _OutputIterator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator>
+__unique_copy(_ForwardIterator __first,
+ _Sent __last,
+ _OutputIterator __result,
+ _BinaryPredicate&& __pred,
+ __unique_copy_tags::__reread_from_input_tag) {
+ if (__first != __last) {
+ _ForwardIterator __i = __first;
+ *__result = *__i;
+ ++__result;
+ while (++__first != __last) {
+ if (!__pred(*__i, *__first)) {
+ *__result = *__first;
++__result;
- while (++__first != __last)
- {
- if (!__pred(*__i, *__first))
- {
- *__result = *__first;
- ++__result;
- __i = __first;
- }
- }
+ __i = __first;
+ }
}
- return __result;
+ }
+ return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result));
}
-template <class _BinaryPredicate, class _InputIterator, class _ForwardIterator>
-_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
-__unique_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result, _BinaryPredicate __pred,
- input_iterator_tag, forward_iterator_tag)
-{
- if (__first != __last)
- {
- *__result = *__first;
- while (++__first != __last)
- if (!__pred(*__result, *__first))
- *++__result = *__first;
- ++__result;
- }
- return __result;
+template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _InputAndOutputIterator>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator>
+__unique_copy(_InputIterator __first,
+ _Sent __last,
+ _InputAndOutputIterator __result,
+ _BinaryPredicate&& __pred,
+ __unique_copy_tags::__reread_from_output_tag) {
+ if (__first != __last) {
+ *__result = *__first;
+ while (++__first != __last)
+ if (!__pred(*__result, *__first))
+ *++__result = *__first;
+ ++__result;
+ }
+ return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result));
}
template <class _InputIterator, class _OutputIterator, class _BinaryPredicate>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_OutputIterator
-unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred)
-{
- return _VSTD::__unique_copy<_BinaryPredicate&>(__first, __last, __result, __pred,
- typename iterator_traits<_InputIterator>::iterator_category(),
- typename iterator_traits<_OutputIterator>::iterator_category());
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
+unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) {
+ using __algo_tag = __conditional_t<
+ is_base_of<forward_iterator_tag, typename iterator_traits<_InputIterator>::iterator_category>::value,
+ __unique_copy_tags::__reread_from_input_tag,
+ __conditional_t<
+ is_base_of<forward_iterator_tag, typename iterator_traits<_OutputIterator>::iterator_category>::value &&
+ is_same< typename iterator_traits<_InputIterator>::value_type,
+ typename iterator_traits<_OutputIterator>::value_type>::value,
+ __unique_copy_tags::__reread_from_output_tag,
+ __unique_copy_tags::__read_from_tmp_value_tag> >;
+ return std::__unique_copy<_ClassicAlgPolicy>(
+ std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag())
+ .second;
}
template <class _InputIterator, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_OutputIterator
-unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
-{
- typedef typename iterator_traits<_InputIterator>::value_type __v;
- return _VSTD::unique_copy(__first, __last, __result, __equal_to<__v>());
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
+unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+ return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to());
}
-
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H
diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h
index fa9a8fbf2dde..0f661e10a74d 100644
--- a/libcxx/include/__algorithm/unwrap_iter.h
+++ b/libcxx/include/__algorithm/unwrap_iter.h
@@ -12,8 +12,10 @@
#include <__config>
#include <__iterator/iterator_traits.h>
#include <__memory/pointer_traits.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_copy_constructible.h>
+#include <__utility/declval.h>
#include <__utility/move.h>
-#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -57,7 +59,7 @@ struct __unwrap_iter_impl<_Iter, true> {
template<class _Iter,
class _Impl = __unwrap_iter_impl<_Iter>,
__enable_if_t<is_copy_constructible<_Iter>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
decltype(_Impl::__unwrap(std::declval<_Iter>())) __unwrap_iter(_Iter __i) _NOEXCEPT {
return _Impl::__unwrap(__i);
}
diff --git a/libcxx/include/__algorithm/unwrap_range.h b/libcxx/include/__algorithm/unwrap_range.h
new file mode 100644
index 000000000000..2c5d23e69f10
--- /dev/null
+++ b/libcxx/include/__algorithm/unwrap_range.h
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_UNWRAP_RANGE_H
+#define _LIBCPP___ALGORITHM_UNWRAP_RANGE_H
+
+#include <__algorithm/unwrap_iter.h>
+#include <__concepts/constructible.h>
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/next.h>
+#include <__utility/declval.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// __unwrap_range and __rewrap_range are used to unwrap ranges which may have different iterator and sentinel types.
+// __unwrap_iter and __rewrap_iter don't work for this, because they assume that the iterator and sentinel have
+// the same type. __unwrap_range tries to get two iterators and then forward to __unwrap_iter.
+
+#if _LIBCPP_STD_VER > 17
+template <class _Iter, class _Sent>
+struct __unwrap_range_impl {
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __sent)
+ requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>
+ {
+ auto __last = ranges::next(__first, __sent);
+ return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Sent __last) {
+ return pair{std::move(__first), std::move(__last)};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto
+ __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter)
+ requires random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>
+ {
+ return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __rewrap(const _Iter&, _Iter __iter)
+ requires (!(random_access_iterator<_Iter> && sized_sentinel_for<_Sent, _Iter>))
+ {
+ return __iter;
+ }
+};
+
+template <class _Iter>
+struct __unwrap_range_impl<_Iter, _Iter> {
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __unwrap(_Iter __first, _Iter __last) {
+ return pair{std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last))};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto
+ __rewrap(_Iter __orig_iter, decltype(std::__unwrap_iter(__orig_iter)) __iter) {
+ return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
+ }
+};
+
+template <class _Iter, class _Sent>
+_LIBCPP_HIDE_FROM_ABI constexpr auto __unwrap_range(_Iter __first, _Sent __last) {
+ return __unwrap_range_impl<_Iter, _Sent>::__unwrap(std::move(__first), std::move(__last));
+}
+
+template <
+ class _Sent,
+ class _Iter,
+ class _Unwrapped = decltype(std::__unwrap_range(std::declval<_Iter>(), std::declval<_Sent>()))>
+_LIBCPP_HIDE_FROM_ABI constexpr _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) {
+ return __unwrap_range_impl<_Iter, _Sent>::__rewrap(std::move(__orig_iter), std::move(__iter));
+}
+#else // _LIBCPP_STD_VER > 17
+template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declval<_Iter>()))>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair<_Unwrapped, _Unwrapped> __unwrap_range(_Iter __first, _Iter __last) {
+ return std::make_pair(std::__unwrap_iter(std::move(__first)), std::__unwrap_iter(std::move(__last)));
+}
+
+template <class _Iter, class _Unwrapped = decltype(std::__unwrap_iter(std::declval<_Iter>()))>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap_range(_Iter __orig_iter, _Unwrapped __iter) {
+ return std::__rewrap_iter(std::move(__orig_iter), std::move(__iter));
+}
+#endif // _LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___ALGORITHM_UNWRAP_RANGE_H
diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h
index 1045380bc84e..96552ce1f8ac 100644
--- a/libcxx/include/__algorithm/upper_bound.h
+++ b/libcxx/include/__algorithm/upper_bound.h
@@ -28,7 +28,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _AlgPolicy, class _Compare, class _Iter, class _Sent, class _Tp, class _Proj>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _Iter
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
__upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp, _Proj&& __proj) {
auto __len = _IterOps<_AlgPolicy>::distance(__first, __last);
while (__len != 0) {
@@ -45,7 +45,7 @@ __upper_bound(_Iter __first, _Sent __last, const _Tp& __value, _Compare&& __comp
}
template <class _ForwardIterator, class _Tp, class _Compare>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value, _Compare __comp) {
static_assert(is_copy_constructible<_ForwardIterator>::value,
"Iterator has to be copy constructible");
@@ -54,7 +54,7 @@ upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __valu
}
template <class _ForwardIterator, class _Tp>
-_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator
+_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
upper_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
return std::upper_bound(
std::move(__first),