Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] Use forwarding refs for predicates and projections in algorithms helpers #133097

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

imdj
Copy link
Contributor

@imdj imdj commented Mar 26, 2025

Pass predicates, projections, and comparators using forward referencing instead of lvalue refs in algorithms helpers.

Proposed fix for issue:

Copy link

github-actions bot commented Mar 26, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@imdj imdj marked this pull request as ready for review March 27, 2025 03:55
@imdj imdj requested a review from a team as a code owner March 27, 2025 03:55
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 27, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 27, 2025

@llvm/pr-subscribers-libcxx

Author: Imad Aldij (imdj)

Changes

Pass predicates, projections, and comparators using forward referencing instead of lvalue refs in algorithms helpers.

Proposed fix for issue:

  • #133065

Patch is 50.86 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133097.diff

51 Files Affected:

  • (modified) libcxx/include/__algorithm/adjacent_find.h (+1-1)
  • (modified) libcxx/include/__algorithm/all_of.h (+1-1)
  • (modified) libcxx/include/__algorithm/any_of.h (+1-1)
  • (modified) libcxx/include/__algorithm/copy_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/count.h (+1-1)
  • (modified) libcxx/include/__algorithm/count_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/equal.h (+8-2)
  • (modified) libcxx/include/__algorithm/find.h (+3-3)
  • (modified) libcxx/include/__algorithm/find_end.h (+3-3)
  • (modified) libcxx/include/__algorithm/find_segment_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/lexicographical_compare.h (+8-2)
  • (modified) libcxx/include/__algorithm/lower_bound.h (+4-4)
  • (modified) libcxx/include/__algorithm/make_projected.h (+4-3)
  • (modified) libcxx/include/__algorithm/min_element.h (+1-1)
  • (modified) libcxx/include/__algorithm/minmax_element.h (+4-4)
  • (modified) libcxx/include/__algorithm/mismatch.h (+13-7)
  • (modified) libcxx/include/__algorithm/ranges_ends_with.h (+9-9)
  • (modified) libcxx/include/__algorithm/ranges_find.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_find_first_of.h (+3-3)
  • (modified) libcxx/include/__algorithm/ranges_find_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_find_last.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_for_each.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_is_heap.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_is_heap_until.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_is_partitioned.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_is_permutation.h (+3-3)
  • (modified) libcxx/include/__algorithm/ranges_is_sorted_until.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_lexicographical_compare.h (+3-3)
  • (modified) libcxx/include/__algorithm/ranges_make_heap.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_min_element.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_mismatch.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_none_of.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_nth_element.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_partial_sort.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_partition_copy.h (+2-2)
  • (modified) libcxx/include/__algorithm/ranges_partition_point.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_pop_heap.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_push_heap.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_remove_copy_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_remove_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_replace_copy_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_replace_if.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_search.h (+3-3)
  • (modified) libcxx/include/__algorithm/ranges_search_n.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_sort.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_sort_heap.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_stable_sort.h (+1-1)
  • (modified) libcxx/include/__algorithm/ranges_transform.h (+3-3)
  • (modified) libcxx/include/__algorithm/search.h (+24-6)
  • (modified) libcxx/include/__algorithm/search_n.h (+4-4)
  • (modified) libcxx/include/__algorithm/sort.h (+2-2)
diff --git a/libcxx/include/__algorithm/adjacent_find.h b/libcxx/include/__algorithm/adjacent_find.h
index 2508250d8796c..89cdc8fa0ae94 100644
--- a/libcxx/include/__algorithm/adjacent_find.h
+++ b/libcxx/include/__algorithm/adjacent_find.h
@@ -27,7 +27,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Iter, class _Sent, class _Pred, class _Proj>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter
-__adjacent_find(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
+__adjacent_find(_Iter __first, _Sent __last, _Pred&& __pred, _Proj&& __proj) {
   if (__first == __last)
     return __first;
 
diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h
index 6acc117fc47bc..a2efff1296445 100644
--- a/libcxx/include/__algorithm/all_of.h
+++ b/libcxx/include/__algorithm/all_of.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Iter, class _Sent, class _Proj, class _Pred>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-__all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
+__all_of(_Iter __first, _Sent __last, _Pred&& __pred, _Proj&& __proj) {
   for (; __first != __last; ++__first) {
     if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
       return false;
diff --git a/libcxx/include/__algorithm/any_of.h b/libcxx/include/__algorithm/any_of.h
index 4b6eb94517286..15b82754977d4 100644
--- a/libcxx/include/__algorithm/any_of.h
+++ b/libcxx/include/__algorithm/any_of.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Iter, class _Sent, class _Proj, class _Pred>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
-__any_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
+__any_of(_Iter __first, _Sent __last, _Pred&& __pred, _Proj&& __proj) {
   for (; __first != __last; ++__first) {
     if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
       return true;
diff --git a/libcxx/include/__algorithm/copy_if.h b/libcxx/include/__algorithm/copy_if.h
index ffea621fc0618..d4b5ba99d4658 100644
--- a/libcxx/include/__algorithm/copy_if.h
+++ b/libcxx/include/__algorithm/copy_if.h
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _InIter, class _Sent, class _OutIter, class _Proj, class _Pred>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
-__copy_if(_InIter __first, _Sent __last, _OutIter __result, _Pred& __pred, _Proj& __proj) {
+__copy_if(_InIter __first, _Sent __last, _OutIter __result, _Pred&& __pred, _Proj&& __proj) {
   for (; __first != __last; ++__first) {
     if (std::__invoke(__pred, std::__invoke(__proj, *__first))) {
       *__result = *__first;
diff --git a/libcxx/include/__algorithm/count.h b/libcxx/include/__algorithm/count.h
index 0cbe9b6e61b98..5bbb9e36d4225 100644
--- a/libcxx/include/__algorithm/count.h
+++ b/libcxx/include/__algorithm/count.h
@@ -33,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 // generic implementation
 template <class _AlgPolicy, class _Iter, class _Sent, class _Tp, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>
-__count(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
+__count(_Iter __first, _Sent __last, const _Tp& __value, _Proj&& __proj) {
   typename _IterOps<_AlgPolicy>::template __difference_type<_Iter> __r(0);
   for (; __first != __last; ++__first)
     if (std::__invoke(__proj, *__first) == __value)
diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index 26f945e6bd98c..a905ad0f9b516 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _AlgPolicy, class _Iter, class _Sent, class _Proj, class _Pred>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __policy_iter_diff_t<_AlgPolicy, _Iter>
-__count_if(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
+__count_if(_Iter __first, _Sent __last, _Pred&& __pred, _Proj&& __proj) {
   __policy_iter_diff_t<_AlgPolicy, _Iter> __counter(0);
   for (; __first != __last; ++__first) {
     if (std::__invoke(__pred, std::__invoke(__proj, *__first)))
diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h
index 5a8c9504ede1d..8b922c1b4a8db 100644
--- a/libcxx/include/__algorithm/equal.h
+++ b/libcxx/include/__algorithm/equal.h
@@ -208,7 +208,13 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first
 
 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2>
 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
-    _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __comp, _Proj1& __proj1, _Proj2& __proj2) {
+    _Iter1 __first1,
+    _Sent1 __last1,
+    _Iter2 __first2,
+    _Sent2 __last2,
+    _Pred&& __comp,
+    _Proj1&& __proj1,
+    _Proj2&& __proj2) {
   while (__first1 != __last1 && __first2 != __last2) {
     if (!std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
       return false;
@@ -228,7 +234,7 @@ template <class _Tp,
                             __libcpp_is_trivially_equality_comparable<_Tp, _Up>::value,
                         int> = 0>
 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-__equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, _Proj2&) {
+__equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&&, _Proj2&&) {
   return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
 }
 
diff --git a/libcxx/include/__algorithm/find.h b/libcxx/include/__algorithm/find.h
index a7d9374b3a1c8..fa8f5b5ef8c5a 100644
--- a/libcxx/include/__algorithm/find.h
+++ b/libcxx/include/__algorithm/find.h
@@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 // generic implementation
 template <class _Iter, class _Sent, class _Tp, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
-__find(_Iter __first, _Sent __last, const _Tp& __value, _Proj& __proj) {
+__find(_Iter __first, _Sent __last, const _Tp& __value, _Proj&& __proj) {
   for (; __first != __last; ++__first)
     if (std::__invoke(__proj, *__first) == __value)
       break;
@@ -88,7 +88,7 @@ template <class _Tp,
                             is_signed<_Tp>::value == is_signed<_Up>::value,
                         int> = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
-__find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj& __proj) {
+__find(_Tp* __first, _Tp* __last, const _Up& __value, _Proj&& __proj) {
   if (__value < numeric_limits<_Tp>::min() || __value > numeric_limits<_Tp>::max())
     return __last;
   return std::__find(__first, __last, _Tp(__value), __proj);
@@ -151,7 +151,7 @@ template <class _SegmentedIterator,
           class _Proj,
           __enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
-__find(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj& __proj) {
+__find(_SegmentedIterator __first, _SegmentedIterator __last, const _Tp& __value, _Proj&& __proj) {
   return std::__find_segment_if(std::move(__first), std::move(__last), __find_segment<_Tp>(__value), __proj);
 }
 
diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h
index 86b4a3e2e3689..06d442bd029e9 100644
--- a/libcxx/include/__algorithm/find_end.h
+++ b/libcxx/include/__algorithm/find_end.h
@@ -37,9 +37,9 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
     _Sent1 __last1,
     _Iter2 __first2,
     _Sent2 __last2,
-    _Pred& __pred,
-    _Proj1& __proj1,
-    _Proj2& __proj2,
+    _Pred&& __pred,
+    _Proj1&& __proj1,
+    _Proj2&& __proj2,
     forward_iterator_tag,
     forward_iterator_tag) {
   // modeled after search algorithm
diff --git a/libcxx/include/__algorithm/find_segment_if.h b/libcxx/include/__algorithm/find_segment_if.h
index 9d6064f3e283a..f77b1af4042ff 100644
--- a/libcxx/include/__algorithm/find_segment_if.h
+++ b/libcxx/include/__algorithm/find_segment_if.h
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _SegmentedIterator, class _Pred, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
-__find_segment_if(_SegmentedIterator __first, _SegmentedIterator __last, _Pred __pred, _Proj& __proj) {
+__find_segment_if(_SegmentedIterator __first, _SegmentedIterator __last, _Pred __pred, _Proj&& __proj) {
   using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
 
   auto __sfirst = _Traits::__segment(__first);
diff --git a/libcxx/include/__algorithm/lexicographical_compare.h b/libcxx/include/__algorithm/lexicographical_compare.h
index ebe7e3b56a292..0467cdcfb4eaf 100644
--- a/libcxx/include/__algorithm/lexicographical_compare.h
+++ b/libcxx/include/__algorithm/lexicographical_compare.h
@@ -41,7 +41,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Proj1, class _Proj2, class _Comp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __lexicographical_compare(
-    _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
+    _Iter1 __first1,
+    _Sent1 __last1,
+    _Iter2 __first2,
+    _Sent2 __last2,
+    _Comp&& __comp,
+    _Proj1&& __proj1,
+    _Proj2&& __proj2) {
   while (__first2 != __last2) {
     if (__first1 == __last1 ||
         std::__invoke(__comp, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
@@ -70,7 +76,7 @@ template <class _Tp,
                             __is_identity<_Proj1>::value && __is_identity<_Proj2>::value,
                         int> = 0>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
-__lexicographical_compare(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Comp&, _Proj1&, _Proj2&) {
+__lexicographical_compare(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Comp&, _Proj1&&, _Proj2&&) {
   if constexpr (__is_trivially_lexicographically_comparable_v<_Tp, _Tp>) {
     auto __res =
         std::__constexpr_memcmp(__first1, __first2, __element_count(std::min(__last1 - __first1, __last2 - __first2)));
diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index 4fba6748e6d71..d07533d0fca8c 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -31,8 +31,8 @@ template <class _AlgPolicy, class _Iter, class _Type, class _Proj, class _Comp>
     _Iter __first,
     const _Type& __value,
     typename iterator_traits<_Iter>::difference_type __len,
-    _Comp& __comp,
-    _Proj& __proj) {
+    _Comp&& __comp,
+    _Proj&& __proj) {
   while (__len != 0) {
     auto __l2 = std::__half_positive(__len);
     _Iter __m = __first;
@@ -58,7 +58,7 @@ template <class _AlgPolicy, class _Iter, class _Type, class _Proj, class _Comp>
 // comparisons.
 template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
-__lower_bound_onesided(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
+__lower_bound_onesided(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp&& __comp, _Proj&& __proj) {
   // step = 0, ensuring we can always short-circuit when distance is 1 later on
   if (__first == __last || !std::__invoke(__comp, std::__invoke(__proj, *__first), __value))
     return __first;
@@ -84,7 +84,7 @@ __lower_bound_onesided(_ForwardIterator __first, _Sent __last, const _Type& __va
 
 template <class _AlgPolicy, class _ForwardIterator, class _Sent, class _Type, class _Proj, class _Comp>
 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
-__lower_bound(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp& __comp, _Proj& __proj) {
+__lower_bound(_ForwardIterator __first, _Sent __last, const _Type& __value, _Comp&& __comp, _Proj&& __proj) {
   const auto __dist = _IterOps<_AlgPolicy>::distance(__first, __last);
   return std::__lower_bound_bisecting<_AlgPolicy>(__first, __value, __dist, __comp, __proj);
 }
diff --git a/libcxx/include/__algorithm/make_projected.h b/libcxx/include/__algorithm/make_projected.h
index 4a25822938751..950daf05a4f75 100644
--- a/libcxx/include/__algorithm/make_projected.h
+++ b/libcxx/include/__algorithm/make_projected.h
@@ -30,7 +30,7 @@ struct _ProjectedPred {
   _Pred& __pred; // Can be a unary or a binary predicate.
   _Proj& __proj;
 
-  _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg)
+  _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred&& __pred_arg, _Proj&& __proj_arg)
       : __pred(__pred_arg), __proj(__proj_arg) {}
 
   template <class _Tp>
@@ -55,7 +55,7 @@ template <
     class _Pred,
     class _Proj,
     __enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value), int> = 0>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred&& __pred, _Proj&& __proj) {
   return _ProjectedPred<_Pred, _Proj>(__pred, __proj);
 }
 
@@ -79,7 +79,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 namespace ranges {
 
 template <class _Comp, class _Proj1, class _Proj2>
-_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
+_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto)
+__make_projected_comp(_Comp&& __comp, _Proj1&& __proj1, _Proj2&& __proj2) {
   if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value &&
                 !is_member_pointer_v<decay_t<_Comp>>) {
     // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index db996365bf1de..9e5f4e43a03fd 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Comp, class _Iter, class _Sent, class _Proj>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
-__min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
+__min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj&& __proj) {
   if (__first == __last)
     return __first;
 
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index dc0c3a818cd57..51a0013f4b10f 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -25,11 +25,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Comp, class _Proj>
 class _MinmaxElementLessFunc {
-  _Comp& __comp_;
-  _Proj& __proj_;
+  _Comp&& __comp_;
+  _Proj&& __proj_;
 
 public:
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _MinmaxElementLessFunc(_Comp& __comp, _Proj& __proj)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _MinmaxElementLessFunc(_Comp&& __comp, _Proj&& __proj)
       : __comp_(__comp), __proj_(__proj) {}
 
   template <class _Iter>
@@ -40,7 +40,7 @@ class _MinmaxElementLessFunc {
 
 template <class _Iter, class _Sent, class _Proj, class _Comp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter, _Iter>
-__minmax_element_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
+__minmax_element_impl(_Iter __first, _Sent __last, _Comp&& __comp, _Proj&& __proj) {
   auto __less = _MinmaxElementLessFunc<_Comp, _Proj>(__comp, __proj);
 
   pair<_Iter, _Iter> __result(__first, __first);
diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h
index a6836792c0581..cb2aa2e055752 100644
--- a/libcxx/include/__algorithm/mismatch.h
+++ b/libcxx/include/__algorithm/mismatch.h
@@ -39,7 +39,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
-__mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+__mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
   while (__first1 != __last1) {
     if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
       break;
@@ -51,7 +51,7 @@ __mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred,
 
 template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2>
-__mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+__mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
   return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2);
 }
 
@@ -126,7 +126,7 @@ template <class _Tp,
                             __is_identity<_Proj1>::value && __is_identity<_Proj2>::value,
                         int> = 0>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*>
-__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred&, _Proj1&, _Proj2&) {
+__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred&, _Proj1&&, _Proj2&&) {
   return std::__mismatch_vectorized(__first1, __last1, __first2);
 }
 
@@ -139,7 +139,7 @@ template <class _Tp,
                             __can_map_to_integer_v<_Tp> && __libcpp_is_trivially_equality_comparable<_Tp, _Tp>::value,
                         int> = 0>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*>
-__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
   if (__libcpp_is_constant_evaluated()) {
     return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2);
   } else {
@@ -168,7 +168,13 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi
 #if _LIBCPP_STD_VER >= 14
 template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch(
-    _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+    _Iter1 __first1,
+    _Sent1 __last1,
+    _Iter2 __first2,
+    _Sent2 __last2,
+    _Pred&& __pred,
+    _Proj1&& __proj1,
+    _Proj2&& __proj2) {
   while (__first1 != __last1 && __first2 != __last2) {
     if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
       break;
@@ -179,8 +185,8 @@ template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, c
 }
 
 template <class _Tp, class _Pred, class _Proj1, class _Proj2>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*>
-__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> __mismatch(
+    _Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred&& __pred, _Proj1&& __proj1, _Proj2&& __proj2) {
   auto __len = std::min(__last1 - __first1, __last2 - __first2);
   return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2);
 }
diff --git a/libcxx/include/__algorithm/ranges_ends_with.h b/libcxx/include/__algorithm/ranges_ends_with.h
index 3621bda389123..24d9ce6293f29 100644
--- a/libcxx/include/__algorithm/ranges_ends_with.h
+++ b/libcxx/include/__a...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants