[libcxx-commits] [libcxx] [libc++] <algorithm>: __is_callable checks whether the callable can be called with rvalue (PR #73451)

Nhat Nguyen via libcxx-commits libcxx-commits at lists.llvm.org
Mon Dec 4 21:06:31 PST 2023


https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/73451

>From 0b45818efdf587f75d93ef01a153f1f9c463912b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CNhat?= <“nhat7203 at gmail.com”>
Date: Sun, 26 Nov 2023 12:13:00 -0500
Subject: [PATCH 1/3] change static assert

---
 libcxx/include/__algorithm/equal_range.h      |  5 +++--
 libcxx/include/__algorithm/includes.h         |  5 +++--
 libcxx/include/__algorithm/is_permutation.h   |  5 +++--
 libcxx/include/__algorithm/lower_bound.h      |  5 +++--
 libcxx/include/__algorithm/min_element.h      |  6 +++---
 libcxx/include/__algorithm/minmax_element.h   |  5 +++--
 .../include/__algorithm/partial_sort_copy.h   |  5 +++--
 .../random/random.uniform.real/test.cpp       | 19 +++++++++++++++++++
 8 files changed, 40 insertions(+), 15 deletions(-)
 create mode 100644 libcxx/test/libcxx/random/random.uniform.real/test.cpp

diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h
index dc1268a6ff110..9528635730f75 100644
--- a/libcxx/include/__algorithm/equal_range.h
+++ b/libcxx/include/__algorithm/equal_range.h
@@ -60,8 +60,9 @@ __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_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_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
   static_assert(is_copy_constructible<_ForwardIterator>::value,
                 "Iterator has to be copy constructible");
   return std::__equal_range<_ClassicAlgPolicy>(
diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h
index 88253e2653d27..9e20fe6174f33 100644
--- a/libcxx/include/__algorithm/includes.h
+++ b/libcxx/include/__algorithm/includes.h
@@ -45,8 +45,9 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     _InputIterator2 __first2,
     _InputIterator2 __last2,
     _Compare __comp) {
-  static_assert(__is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value,
-      "Comparator has to be callable");
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
 
   return std::__includes(
       std::move(__first1),
diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index 105a0732283c9..17aaf12ceeda2 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -191,8 +191,9 @@ template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredica
 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
                _BinaryPredicate __pred) {
-  static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
-      "The predicate has to be callable");
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
 
   return std::__is_permutation<_ClassicAlgPolicy>(
       std::move(__first1), std::move(__last1), std::move(__first2), __pred);
diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index 91c3bdaafd0cf..399ebaa88e565 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -49,8 +49,9 @@ _Iter __lower_bound(_Iter __first, _Sent __last, const _Type& __value, _Comp& __
 template <class _ForwardIterator, class _Tp, class _Compare>
 _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");
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
   auto __proj = std::__identity();
   return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj);
 }
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index 45f3e85ef92d9..3e8f1a31bced4 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -54,9 +54,9 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
       "std::min_element requires a ForwardIterator");
-  static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value,
-              "The comparator has to be callable");
-
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
   return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
 }
 
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index 5bcaf8354d9ff..49b62b87c6b26 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -85,8 +85,9 @@ pair<_ForwardIterator, _ForwardIterator>
 minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
                 "std::minmax_element requires a ForwardIterator");
-  static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value,
-                "The comparator has to be callable");
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
   auto __proj = __identity();
   return std::__minmax_element_impl(__first, __last, __comp, __proj);
 }
diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h
index b9635c51d5fab..a0b0525b4ee9e 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -65,8 +65,9 @@ _RandomAccessIterator
 partial_sort_copy(_InputIterator __first, _InputIterator __last,
                   _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
 {
-  static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value,
-                "Comparator has to be callable");
+  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
+  static_assert(
+      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
 
   auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(__first, __last, __result_first, __result_last,
       static_cast<__comp_ref_type<_Compare> >(__comp), __identity(), __identity());
diff --git a/libcxx/test/libcxx/random/random.uniform.real/test.cpp b/libcxx/test/libcxx/random/random.uniform.real/test.cpp
new file mode 100644
index 0000000000000..bc84e362034cc
--- /dev/null
+++ b/libcxx/test/libcxx/random/random.uniform.real/test.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+// template<_RealType = double>
+// class uniform_real_distribution;
+
+// result_type must be floating type, int type is unsupported
+
+#include <random>
+
+// expected-error@*:* {{static assertion failed due to requirement '__libcpp_random_is_valid_realtype<int>::value': RealType must be a supported floating-point type}}
+struct test_random : public std::uniform_real_distribution<int> {};

>From f0925268b095ce6a4a1166cd444c511823a556c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CNhat?= <“nhat7203 at gmail.com”>
Date: Mon, 27 Nov 2023 22:56:45 -0500
Subject: [PATCH 2/3] remove strong static asserts

---
 libcxx/include/__algorithm/includes.h          | 3 +--
 libcxx/include/__algorithm/is_permutation.h    | 4 +---
 libcxx/include/__algorithm/min_element.h       | 3 +--
 libcxx/include/__algorithm/minmax_element.h    | 3 +--
 libcxx/include/__algorithm/partial_sort_copy.h | 3 +--
 5 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h
index 9e20fe6174f33..54a3893a4ddaf 100644
--- a/libcxx/include/__algorithm/includes.h
+++ b/libcxx/include/__algorithm/includes.h
@@ -45,9 +45,8 @@ _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     _InputIterator2 __first2,
     _InputIterator2 __last2,
     _Compare __comp) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(
-      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
+      __is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, "Comparator has to be callable");
 
   return std::__includes(
       std::move(__first1),
diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index 17aaf12ceeda2..2e74064b596c8 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -191,9 +191,7 @@ template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredica
 _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
                _BinaryPredicate __pred) {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
-  static_assert(
-      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
+  static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
 
   return std::__is_permutation<_ClassicAlgPolicy>(
       std::move(__first1), std::move(__last1), std::move(__first2), __pred);
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index 3e8f1a31bced4..f7b3a05c5aef0 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -54,9 +54,8 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
       "std::min_element requires a ForwardIterator");
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(
-      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
+      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
 }
 
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index 49b62b87c6b26..49dcc5b17dc2a 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -85,9 +85,8 @@ pair<_ForwardIterator, _ForwardIterator>
 minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
                 "std::minmax_element requires a ForwardIterator");
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(
-      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
+      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   auto __proj = __identity();
   return std::__minmax_element_impl(__first, __last, __comp, __proj);
 }
diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h
index a0b0525b4ee9e..35337d41be323 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -65,9 +65,8 @@ _RandomAccessIterator
 partial_sort_copy(_InputIterator __first, _InputIterator __last,
                   _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
 {
-  static_assert(__is_callable<_Compare&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
   static_assert(
-      __is_callable<_Compare const&, decltype(*__first), const _Tp&>::value, "The comparator has to be const-callable");
+      __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());

>From 16c779f0ce86a34c562c6662539a08260965b87a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9CNhat?= <“nhat7203 at gmail.com”>
Date: Tue, 5 Dec 2023 00:06:14 -0500
Subject: [PATCH 3/3] syntax fix

---
 libcxx/include/__algorithm/is_permutation.h    | 1 +
 libcxx/include/__algorithm/min_element.h       | 3 +--
 libcxx/include/__algorithm/minmax_element.h    | 3 +--
 libcxx/include/__algorithm/partial_sort_copy.h | 3 +--
 4 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h
index 2e74064b596c8..105a0732283c9 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -192,6 +192,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2,
                _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);
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index f7b3a05c5aef0..95b7628b45b3b 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -54,8 +54,7 @@ min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp)
 {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
       "std::min_element requires a ForwardIterator");
-  static_assert(
-      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
+  static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
 }
 
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index 49dcc5b17dc2a..790e5cfde4696 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -85,8 +85,7 @@ pair<_ForwardIterator, _ForwardIterator>
 minmax_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
   static_assert(__has_forward_iterator_category<_ForwardIterator>::value,
                 "std::minmax_element requires a ForwardIterator");
-  static_assert(
-      __is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
+  static_assert(__is_callable<_Compare, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
   auto __proj = __identity();
   return std::__minmax_element_impl(__first, __last, __comp, __proj);
 }
diff --git a/libcxx/include/__algorithm/partial_sort_copy.h b/libcxx/include/__algorithm/partial_sort_copy.h
index 35337d41be323..3e50d5b56a175 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -65,8 +65,7 @@ _RandomAccessIterator
 partial_sort_copy(_InputIterator __first, _InputIterator __last,
                   _RandomAccessIterator __result_first, _RandomAccessIterator __result_last, _Compare __comp)
 {
-  static_assert(
-      __is_callable<_Compare, decltype(*__first), decltype(*__result_first)>::value, "Comparator has to be callable");
+  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());



More information about the libcxx-commits mailing list