diff options
Diffstat (limited to 'libcxx/include/__algorithm')
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), | 
