[libc++] Check correctly ref-qualified __is_callable in algorithms (#73451)
We were only checking that the comparator was rvalue callable,
when in reality the algorithms always call comparators as lvalues.
This patch also refactors the tests for callable requirements and
expands it to a few missing algorithms.
Fixes #69554
diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h
index 09bbf8f..676e436 100644
--- a/libcxx/include/__algorithm/equal_range.h
+++ b/libcxx/include/__algorithm/equal_range.h
@@ -62,7 +62,7 @@
template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD _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_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible");
return std::__equal_range<_ClassicAlgPolicy>(
std::move(__first),
diff --git a/libcxx/include/__algorithm/includes.h b/libcxx/include/__algorithm/includes.h
index 62af03c..0ad09a9 100644
--- a/libcxx/include/__algorithm/includes.h
+++ b/libcxx/include/__algorithm/includes.h
@@ -54,7 +54,7 @@
_InputIterator2 __last2,
_Compare __comp) {
static_assert(
- __is_callable<_Compare, decltype(*__first1), decltype(*__first2)>::value, "Comparator has to be callable");
+ __is_callable<_Compare&, decltype(*__first1), decltype(*__first2)>::value, "The 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 2ddfb32..9dcfcf1 100644
--- a/libcxx/include/__algorithm/is_permutation.h
+++ b/libcxx/include/__algorithm/is_permutation.h
@@ -249,8 +249,8 @@
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
_LIBCPP_NODISCARD _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<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
+ "The comparator has to be callable");
return std::__is_permutation<_ClassicAlgPolicy>(std::move(__first1), std::move(__last1), std::move(__first2), __pred);
}
@@ -286,8 +286,8 @@
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
- static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
- "The predicate has to be callable");
+ static_assert(__is_callable<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
+ "The comparator has to be callable");
return std::__is_permutation<_ClassicAlgPolicy>(
std::move(__first1),
diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h
index c417d84..d18ab83 100644
--- a/libcxx/include/__algorithm/lower_bound.h
+++ b/libcxx/include/__algorithm/lower_bound.h
@@ -93,7 +93,7 @@
template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD 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");
auto __proj = std::__identity();
return std::__lower_bound<_ClassicAlgPolicy>(__first, __last, __value, __comp, __proj);
}
diff --git a/libcxx/include/__algorithm/max_element.h b/libcxx/include/__algorithm/max_element.h
index c036726..3e58c40 100644
--- a/libcxx/include/__algorithm/max_element.h
+++ b/libcxx/include/__algorithm/max_element.h
@@ -13,6 +13,7 @@
#include <__algorithm/comp_ref_type.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__type_traits/is_callable.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -37,6 +38,8 @@
template <class _ForwardIterator, class _Compare>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
max_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
+ static_assert(
+ __is_callable<_Compare&, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
return std::__max_element<__comp_ref_type<_Compare> >(__first, __last, __comp);
}
diff --git a/libcxx/include/__algorithm/min_element.h b/libcxx/include/__algorithm/min_element.h
index 65f3594..9a360f9 100644
--- a/libcxx/include/__algorithm/min_element.h
+++ b/libcxx/include/__algorithm/min_element.h
@@ -53,7 +53,7 @@
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");
+ __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.h b/libcxx/include/__algorithm/minmax.h
index 9feda2b..bb7a379 100644
--- a/libcxx/include/__algorithm/minmax.h
+++ b/libcxx/include/__algorithm/minmax.h
@@ -40,7 +40,7 @@
template <class _Tp, class _Compare>
_LIBCPP_NODISCARD 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");
+ static_assert(__is_callable<_Compare&, _Tp, _Tp>::value, "The comparator has to be callable");
__identity __proj;
auto __ret = std::__minmax_element_impl(__t.begin(), __t.end(), __comp, __proj);
return pair<_Tp, _Tp>(*__ret.first, *__ret.second);
diff --git a/libcxx/include/__algorithm/minmax_element.h b/libcxx/include/__algorithm/minmax_element.h
index 43cb233..23929c9 100644
--- a/libcxx/include/__algorithm/minmax_element.h
+++ b/libcxx/include/__algorithm/minmax_element.h
@@ -84,7 +84,7 @@
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");
+ __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 ef7c9d3..6d44b4f 100644
--- a/libcxx/include/__algorithm/partial_sort_copy.h
+++ b/libcxx/include/__algorithm/partial_sort_copy.h
@@ -76,8 +76,8 @@
_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,
+ "The comparator has to be callable");
auto __result = std::__partial_sort_copy<_ClassicAlgPolicy>(
__first,
diff --git a/libcxx/include/__algorithm/search.h b/libcxx/include/__algorithm/search.h
index b82ca78..7316e5e 100644
--- a/libcxx/include/__algorithm/search.h
+++ b/libcxx/include/__algorithm/search.h
@@ -166,8 +166,8 @@
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
- static_assert(__is_callable<_BinaryPredicate, decltype(*__first1), decltype(*__first2)>::value,
- "BinaryPredicate has to be callable");
+ static_assert(__is_callable<_BinaryPredicate&, decltype(*__first1), decltype(*__first2)>::value,
+ "The comparator has to be callable");
auto __proj = __identity();
return std::__search_impl(__first1, __last1, __first2, __last2, __pred, __proj, __proj).first;
}
diff --git a/libcxx/include/__algorithm/search_n.h b/libcxx/include/__algorithm/search_n.h
index 771647d..f980638 100644
--- a/libcxx/include/__algorithm/search_n.h
+++ b/libcxx/include/__algorithm/search_n.h
@@ -139,7 +139,7 @@
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator search_n(
_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred) {
static_assert(
- __is_callable<_BinaryPredicate, decltype(*__first), const _Tp&>::value, "BinaryPredicate has to be callable");
+ __is_callable<_BinaryPredicate&, decltype(*__first), const _Tp&>::value, "The comparator has to be callable");
auto __proj = __identity();
return std::__search_n_impl(__first, __last, std::__convert_to_integral(__count), __value, __pred, __proj).first;
}
diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h
index c39dec2..43d1c51 100644
--- a/libcxx/include/__algorithm/upper_bound.h
+++ b/libcxx/include/__algorithm/upper_bound.h
@@ -18,6 +18,7 @@
#include <__iterator/advance.h>
#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
+#include <__type_traits/is_callable.h>
#include <__type_traits/is_constructible.h>
#include <__utility/move.h>
@@ -50,6 +51,7 @@
template <class _ForwardIterator, class _Tp, class _Compare>
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
upper_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_copy_constructible<_ForwardIterator>::value, "Iterator has to be copy constructible");
return std::__upper_bound<_ClassicAlgPolicy>(
std::move(__first), std::move(__last), __value, std::move(__comp), std::__identity());
diff --git a/libcxx/src/regex.cpp b/libcxx/src/regex.cpp
index 9dc0c69..6d9f06e 100644
--- a/libcxx/src/regex.cpp
+++ b/libcxx/src/regex.cpp
@@ -323,8 +323,8 @@
{"xdigit", ctype_base::xdigit}};
struct use_strcmp {
- bool operator()(const collationnames& x, const char* y) { return strcmp(x.elem_, y) < 0; }
- bool operator()(const classnames& x, const char* y) { return strcmp(x.elem_, y) < 0; }
+ bool operator()(const collationnames& x, const char* y) const { return strcmp(x.elem_, y) < 0; }
+ bool operator()(const classnames& x, const char* y) const { return strcmp(x.elem_, y) < 0; }
};
} // namespace
diff --git a/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp b/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp
new file mode 100644
index 0000000..4a5535e
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/callable-requirements-rvalue.compile.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <algorithm>
+
+// Make sure that we don't error out when passing a comparator that is lvalue callable
+// but not rvalue callable to algorithms. While it is technically ill-formed for users
+// to provide us such predicates, this test is useful for libc++ to ensure that we check
+// predicate requirements correctly (i.e. that we check them on lvalues and not on
+// rvalues). See https://github.com/llvm/llvm-project/issues/69554 for additional
+// context.
+
+#include <algorithm>
+
+#include "test_macros.h"
+
+struct NotRvalueCallable {
+ bool operator()(int a, int b) const& { return a < b; }
+ bool operator()(int, int) && = delete;
+};
+
+void f() {
+ int a[] = {1, 2, 3, 4};
+ (void)std::lower_bound(a, a + 4, 0, NotRvalueCallable{});
+ (void)std::upper_bound(a, a + 4, 0, NotRvalueCallable{});
+ (void)std::minmax({1, 2, 3}, NotRvalueCallable{});
+ (void)std::minmax_element(a, a + 4, NotRvalueCallable{});
+ (void)std::min_element(a, a + 4, NotRvalueCallable{});
+ (void)std::max_element(a, a + 4, NotRvalueCallable{});
+ (void)std::is_permutation(a, a + 4, a, NotRvalueCallable{});
+#if TEST_STD_VER >= 14
+ (void)std::is_permutation(a, a + 4, a, a + 4, NotRvalueCallable{});
+#endif
+ (void)std::includes(a, a + 4, a, a + 4, NotRvalueCallable{});
+ (void)std::equal_range(a, a + 4, 0, NotRvalueCallable{});
+ (void)std::partial_sort_copy(a, a + 4, a, a + 4, NotRvalueCallable{});
+ (void)std::search(a, a + 4, a, a + 4, NotRvalueCallable{});
+ (void)std::search_n(a, a + 4, 4, 0, NotRvalueCallable{});
+}
diff --git a/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp
new file mode 100644
index 0000000..7555d98
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/callable-requirements.verify.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// Ignore spurious errors after the initial static_assert failure.
+// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
+
+// <algorithm>
+
+// Check that calling a classic STL algorithm with various non-callable comparators is diagnosed.
+
+#include <algorithm>
+
+#include "test_macros.h"
+
+struct NotCallable {
+ bool compare(int a, int b) const { return a < b; }
+};
+
+struct NotMutableCallable {
+ bool operator()(int a, int b) = delete;
+ bool operator()(int a, int b) const { return a < b; }
+};
+
+void f() {
+ int a[] = {1, 2, 3, 4};
+ {
+ (void)std::lower_bound(a, a + 4, 0, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::upper_bound(a, a + 4, 0, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::minmax({1, 2, 3}, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::minmax_element(a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::min_element(a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::max_element(a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::is_permutation(a, a + 4, a, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+#if TEST_STD_VER >= 14
+ (void)std::is_permutation(a, a + 4, a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+#endif
+
+ (void)std::includes(a, a + 4, a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::equal_range(a, a + 4, 0, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::partial_sort_copy(a, a + 4, a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::search(a, a + 4, a, a + 4, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::search_n(a, a + 4, 4, 0, &NotCallable::compare);
+ // expected-error@*:* {{The comparator has to be callable}}
+ }
+
+ {
+ (void)std::lower_bound(a, a + 4, 0, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::upper_bound(a, a + 4, 0, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::minmax({1, 2, 3}, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::minmax_element(a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::min_element(a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::max_element(a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::is_permutation(a, a + 4, a, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+#if TEST_STD_VER >= 14
+ (void)std::is_permutation(a, a + 4, a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+#endif
+
+ (void)std::includes(a, a + 4, a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::equal_range(a, a + 4, 0, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::partial_sort_copy(a, a + 4, a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::search(a, a + 4, a, a + 4, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+
+ (void)std::search_n(a, a + 4, 4, 0, NotMutableCallable{});
+ // expected-error@*:* {{The comparator has to be callable}}
+ }
+}
diff --git a/libcxx/test/libcxx/algorithms/callable.verify.cpp b/libcxx/test/libcxx/algorithms/callable.verify.cpp
deleted file mode 100644
index da87ecd..0000000
--- a/libcxx/test/libcxx/algorithms/callable.verify.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03
-
-// <algorithm>
-
-// check that the classical algorithms with non-callable comparators fail
-
-#include <algorithm>
-
-void f() {
- struct S {
- int i;
-
- S(int i_) : i(i_) {}
-
- bool compare(const S&) const;
- };
-
- S a[] = {1, 2, 3, 4};
- (void) std::lower_bound(a, a + 4, 0, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
- (void) std::minmax({S{1}}, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
- (void) std::minmax_element(a, a + 4, &S::compare); // expected-error@*:* {{The comparator has to be callable}}
-}
diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
index bc71150..d20abf3 100644
--- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp
@@ -26,35 +26,35 @@
constexpr explicit Proj(int *copies) : copies_(copies) {}
constexpr Proj(const Proj& rhs) : copies_(rhs.copies_) { *copies_ += 1; }
constexpr Proj& operator=(const Proj&) = default;
- constexpr void *operator()(T) const { return nullptr; }
+ constexpr void* operator()(T) const { return nullptr; }
};
struct Less {
- constexpr bool operator()(void*, void*) const { return false; }
+ constexpr bool operator()(void*, void*) const { return false; }
};
struct Equal {
- constexpr bool operator()(void*, void*) const { return true; }
+ constexpr bool operator()(void*, void*) const { return true; }
};
struct UnaryVoid {
- constexpr void operator()(void*) const {}
+ constexpr void operator()(void*) const {}
};
struct UnaryTrue {
- constexpr bool operator()(void*) const { return true; }
+ constexpr bool operator()(void*) const { return true; }
};
struct NullaryValue {
- constexpr std::nullptr_t operator()() const { return nullptr; }
+ constexpr std::nullptr_t operator()() const { return nullptr; }
};
struct UnaryTransform {
- constexpr T operator()(void*) const { return T(); }
+ constexpr T operator()(void*) const { return T(); }
};
struct BinaryTransform {
- constexpr T operator()(void*, void*) const { return T(); }
+ constexpr T operator()(void*, void*) const { return T(); }
};
constexpr bool all_the_algorithms()
diff --git a/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
index 78a5863..f5ad5a8 100644
--- a/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
+++ b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
@@ -72,9 +72,9 @@
};
struct Pred {
- bool operator()(int, int) { return false; }
- bool operator()(int) { return false; }
- int operator()() { return 0; }
+ bool operator()(int, int) const { return false; }
+ bool operator()(int) const { return false; }
+ int operator()() const { return 0; }
};
void test() {
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
index ea4270e..4e4f889 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/is_permutation_pred.pass.cpp
@@ -51,7 +51,7 @@
};
struct eq {
- bool operator()(const S& a, const S&b) { return a.i_ == b.i_; }
+ bool operator()(const S& a, const S& b) const { return a.i_ == b.i_; }
};
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
index 3bf72e3..2fa3e9f 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp
@@ -32,12 +32,13 @@
}
#endif
-struct count_equal
-{
- static unsigned count;
- template <class T>
- bool operator()(const T& x, const T& y)
- {++count; return x == y;}
+struct count_equal {
+ static unsigned count;
+ template <class T>
+ bool operator()(const T& x, const T& y) const {
+ ++count;
+ return x == y;
+ }
};
unsigned count_equal::count = 0;
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
index f835d2f..cfb82f3 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search_pred.pass.cpp
@@ -36,8 +36,15 @@
{
static unsigned count;
template <class T>
- bool operator()(const T& x, const T& y)
- {++count; return x == y;}
+ bool operator()(const T& x, const T& y) & {
+ ++count;
+ return x == y;
+ };
+ template <class T>
+ bool operator()(const T& x, const T& y) const& {
+ ++count;
+ return x == y;
+ };
};
unsigned count_equal::count = 0;
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
index d103e8c..ebff401 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
@@ -24,11 +24,11 @@
#if TEST_STD_VER >= 11
#include <memory>
-struct indirect_less
-{
- template <class P>
- bool operator()(const P& x, const P& y)
- {return *x < *y;}
+struct indirect_less {
+ template <class P>
+ bool operator()(const P& x, const P& y) const {
+ return *x < *y;
+ }
};
struct S {
@@ -119,7 +119,7 @@
struct less_by_first {
template <typename Pair>
- bool operator()(const Pair& lhs, const Pair& rhs) {
+ bool operator()(const Pair& lhs, const Pair& rhs) const {
return std::less<typename Pair::first_type>()(lhs.first, rhs.first);
}
};
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
index 46c2a42..5ee6d89 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp
@@ -25,21 +25,17 @@
#include "test_macros.h"
-struct indirect_less
-{
- template <class P>
- bool operator()(const P& x, const P& y)
- {return *x < *y;}
+struct indirect_less {
+ template <class P>
+ bool operator()(const P& x, const P& y) const {
+ return *x < *y;
+ }
};
std::mt19937 randomness;
-struct first_only
-{
- bool operator()(const std::pair<int, int>& x, const std::pair<int, int>& y)
- {
- return x.first < y.first;
- }
+struct first_only {
+ bool operator()(const std::pair<int, int>& x, const std::pair<int, int>& y) const { return x.first < y.first; }
};
void test()