[libcxx-commits] [libcxx] 96dbdd7 - [libcxx] adds remaining callable concepts

Christopher Di Bella via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 6 09:36:16 PDT 2021


Author: Christopher Di Bella
Date: 2021-04-06T16:35:57Z
New Revision: 96dbdd753a1f8bfe0d03f13de484fa18c8bca8db

URL: https://github.com/llvm/llvm-project/commit/96dbdd753a1f8bfe0d03f13de484fa18c8bca8db
DIFF: https://github.com/llvm/llvm-project/commit/96dbdd753a1f8bfe0d03f13de484fa18c8bca8db.diff

LOG: [libcxx] adds remaining callable concepts

* `std::predicate`
* `std::relation`
* `std::equivalence_relation`
* `std::strict_weak_order`

Implements parts of:
    - P0898R3 Standard Library Concepts
    - P1754 Rename concepts to standard_case for C++20, while we still can

Differential Revision: https://reviews.llvm.org/D96477

Added: 
    libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp
    libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp

Modified: 
    libcxx/docs/Cxx2aStatusPaperStatus.csv
    libcxx/include/concepts

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Cxx2aStatusPaperStatus.csv b/libcxx/docs/Cxx2aStatusPaperStatus.csv
index fa93be072c1b8..8ff62a5387fe4 100644
--- a/libcxx/docs/Cxx2aStatusPaperStatus.csv
+++ b/libcxx/docs/Cxx2aStatusPaperStatus.csv
@@ -76,7 +76,7 @@
 "`P1209R0 <https://wg21.link/P1209R0>`__","LWG","Adopt Consistent Container Erasure from Library Fundamentals 2 for C++20","San Diego","|Complete|","8.0"
 "`P1210R0 <https://wg21.link/P1210R0>`__","LWG","Completing the Rebase of Library Fundamentals, Version 3, Working Draft","San Diego","* *",""
 "`P1236R1 <https://wg21.link/P1236R1>`__","CWG","Alternative Wording for P0907R4 Signed Integers are Two's Complement","San Diego","* *",""
-"`P1248R1 <https://wg21.link/P1248R1>`__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","* *",""
+"`P1248R1 <https://wg21.link/P1248R1>`__","LWG","Remove CommonReference requirement from StrictWeakOrdering (a.k.a Fixing Relations)","San Diego","|Complete|","13.0"
 "`P1285R0 <https://wg21.link/P1285R0>`__","LWG","Improving Completeness Requirements for Type Traits","San Diego","* *",""
 "`P1353R0 <https://wg21.link/P1353R0>`__","CWG","Missing feature test macros","San Diego","* *",""
 "","","","","",""

diff  --git a/libcxx/include/concepts b/libcxx/include/concepts
index 070e1df64d193..200a17795f9a2 100644
--- a/libcxx/include/concepts
+++ b/libcxx/include/concepts
@@ -426,7 +426,25 @@ concept invocable = requires(_Fn&& __fn, _Args&&... __args) {
 template<class _Fn, class... _Args>
 concept regular_invocable = invocable<_Fn, _Args...>;
 
-#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
+// [concept.predicate]
+template<class _Fn, class... _Args>
+concept predicate =
+  regular_invocable<_Fn, _Args...> && __boolean_testable<invoke_result_t<_Fn, _Args...>>;
+
+// [concept.relation]
+template<class _Rp, class _Tp, class _Up>
+concept relation =
+  predicate<_Rp, _Tp, _Tp> && predicate<_Rp, _Up, _Up> &&
+  predicate<_Rp, _Tp, _Up> && predicate<_Rp, _Up, _Tp>;
+
+// [concept.equiv]
+template<class _Rp, class _Tp, class _Up>
+concept equivalence_relation = relation<_Rp, _Tp, _Up>;
+
+// [concept.strictweakorder]
+template<class _Rp, class _Tp, class _Up>
+concept strict_weak_order = relation<_Rp, _Tp, _Up>;
+#endif //_LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp
new file mode 100644
index 0000000000000..f16024f4e1829
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.compile.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept equivalence_relation;
+
+#include <concepts>
+
+static_assert(std::equivalence_relation<bool(int, int), int, int>);
+static_assert(std::equivalence_relation<bool(int, int), double, double>);
+static_assert(std::equivalence_relation<bool(int, double), double, double>);
+
+static_assert(!std::equivalence_relation<bool (*)(), int, double>);
+static_assert(!std::equivalence_relation<bool (*)(int), int, double>);
+static_assert(!std::equivalence_relation<bool (*)(double), int, double>);
+
+static_assert(
+    !std::equivalence_relation<bool(double, double*), double, double*>);
+static_assert(!std::equivalence_relation<bool(int&, int&), double&, double&>);
+
+struct S1 {};
+static_assert(std::relation<bool (S1::*)(S1*), S1*, S1*>);
+static_assert(std::relation<bool (S1::*)(S1&), S1&, S1&>);
+
+struct S2 {};
+
+struct P1 {
+  bool operator()(S1, S1) const;
+};
+static_assert(std::equivalence_relation<P1, S1, S1>);
+
+struct P2 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+};
+static_assert(!std::equivalence_relation<P2, S1, S2>);
+
+struct P3 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+};
+static_assert(!std::equivalence_relation<P3, S1, S2>);
+
+struct P4 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+static_assert(std::equivalence_relation<P4, S1, S2>);

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..7619c8ce22178
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.equiv/equivalence_relation.subsumption.compile.pass.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept equivalence_relation;
+
+#include <concepts>
+
+struct S1 {};
+struct S2 {};
+
+struct R {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+
+// clang-format off
+template<class F, class T, class U>
+requires std::relation<F, T, U>
+[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::equivalence_relation<F, T, U> && true
+[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_relation() {
+  return true;
+}
+// clang-format on
+
+static_assert(check_equivalence_relation_subsumes_relation<int (*)(int, int),
+                                                           int, int>());
+static_assert(check_equivalence_relation_subsumes_relation<int (*)(int, double),
+                                                           int, double>());
+static_assert(check_equivalence_relation_subsumes_relation<R, S1, S1>());
+static_assert(check_equivalence_relation_subsumes_relation<R, S1, S2>());
+
+// clang-format off
+template<class F, class T, class U>
+requires std::relation<F, T, U> && true
+[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() {
+  return true;
+}
+
+template<class F, class T, class U>
+requires std::equivalence_relation<F, T, U>
+[[nodiscard]] constexpr bool check_relation_subsumes_equivalence_relation() {
+  return false;
+}
+// clang-format on
+
+static_assert(check_relation_subsumes_equivalence_relation<int (*)(int, int),
+                                                           int, int>());
+static_assert(check_relation_subsumes_equivalence_relation<int (*)(int, double),
+                                                           int, double>());
+static_assert(check_relation_subsumes_equivalence_relation<R, S1, S1>());
+static_assert(check_relation_subsumes_equivalence_relation<R, S1, S2>());
+
+// clang-format off
+template<class F, class T, class U>
+requires std::equivalence_relation<F, T, T> && std::equivalence_relation<F, U, U>
+[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::equivalence_relation<F, T, U>
+[[nodiscard]] constexpr bool check_equivalence_relation_subsumes_itself() {
+  return true;
+}
+// clang-format on
+
+static_assert(
+    check_equivalence_relation_subsumes_itself<int (*)(int, int), int, int>());
+static_assert(check_equivalence_relation_subsumes_itself<R, S1, S1>());

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp
new file mode 100644
index 0000000000000..5ad5985d8fa45
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.compile.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept predicate;
+
+#include <concepts>
+
+static_assert(std::predicate<bool()>);
+static_assert(std::predicate<bool (*)()>);
+static_assert(std::predicate<bool (&)()>);
+
+static_assert(!std::predicate<void()>);
+static_assert(!std::predicate<void (*)()>);
+static_assert(!std::predicate<void (&)()>);
+
+struct S {};
+
+static_assert(!std::predicate<S(int), int>);
+static_assert(!std::predicate<S(double), double>);
+static_assert(std::predicate<int S::*, S*>);
+static_assert(std::predicate<int (S::*)(), S*>);
+static_assert(std::predicate<int (S::*)(), S&>);
+static_assert(!std::predicate<void (S::*)(), S*>);
+static_assert(!std::predicate<void (S::*)(), S&>);
+
+static_assert(!std::predicate<bool(S)>);
+static_assert(!std::predicate<bool(S&), S>);
+static_assert(!std::predicate<bool(S&), S const&>);
+static_assert(std::predicate<bool(S&), S&>);
+
+struct Predicate {
+  bool operator()(int, double, char);
+};
+static_assert(std::predicate<Predicate, int, double, char>);
+static_assert(std::predicate<Predicate&, int, double, char>);
+static_assert(!std::predicate<const Predicate, int, double, char>);
+static_assert(!std::predicate<const Predicate&, int, double, char>);
+
+[[nodiscard]] constexpr bool check_lambda(auto) { return false; }
+
+[[nodiscard]] constexpr bool check_lambda(std::predicate auto) { return true; }
+
+static_assert(check_lambda([] { return std::true_type(); }));
+static_assert(check_lambda([]() -> int* { return nullptr; }));
+
+struct boolean {
+  operator bool() const noexcept;
+};
+static_assert(check_lambda([] { return boolean(); }));
+
+struct explicit_bool {
+  explicit operator bool() const noexcept;
+};
+static_assert(!check_lambda([] { return explicit_bool(); }));

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..3ac652626edf5
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.predicate/predicate.subsumption.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept predicate;
+
+#include <concepts>
+
+[[nodiscard]] constexpr bool check_subsumption(std::regular_invocable auto) {
+  return false;
+}
+
+// clang-format off
+template<class F>
+requires std::predicate<F> && true
+[[nodiscard]] constexpr bool check_subsumption(F)
+{
+  return true;
+}
+// clang-format on
+
+static_assert(!check_subsumption([] {}));
+static_assert(check_subsumption([] { return true; }));

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp
new file mode 100644
index 0000000000000..d647c11cb9f10
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.compile.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept relation;
+
+#include <concepts>
+
+static_assert(std::relation<bool(int, int), int, int>);
+static_assert(std::relation<bool(int, int), double, double>);
+static_assert(std::relation<bool(int, double), double, double>);
+
+static_assert(!std::relation<bool(), int, double>);
+static_assert(!std::relation<bool(int), int, double>);
+static_assert(!std::relation<bool(double), int, double>);
+static_assert(!std::relation<bool(double, double*), double, double*>);
+static_assert(!std::relation<bool(int&, int&), double&, double&>);
+
+struct S1 {};
+static_assert(std::relation<bool (S1::*)(S1*), S1*, S1*>);
+static_assert(std::relation<bool (S1::*)(S1&), S1&, S1&>);
+
+struct S2 {};
+
+struct P1 {
+  bool operator()(S1, S1) const;
+};
+static_assert(std::relation<P1, S1, S1>);
+
+struct P2 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+};
+static_assert(!std::relation<P2, S1, S2>);
+
+struct P3 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+};
+static_assert(!std::relation<P3, S1, S2>);
+
+struct P4 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+static_assert(std::relation<P4, S1, S2>);

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..f7a45f2b07518
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.relation/relation.subsumption.compile.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept relation;
+
+#include <concepts>
+
+struct S1 {};
+struct S2 {};
+
+struct R {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+
+// clang-format off
+template<class F, class T, class U>
+requires std::predicate<F, T, T> && std::predicate<F, T, U> &&
+         std::predicate<F, U, T> && std::predicate<F, U, U>
+[[nodiscard]] constexpr bool check_relation_subsumes_predicate() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::relation<F, T, U> && true
+[[nodiscard]] constexpr bool check_relation_subsumes_predicate() {
+  return true;
+}
+// clang-format on
+
+static_assert(
+    check_relation_subsumes_predicate<int (*)(int, double), int, int>());
+static_assert(
+    check_relation_subsumes_predicate<int (*)(int, double), int, double>());
+static_assert(check_relation_subsumes_predicate<R, S1, S1>());
+static_assert(check_relation_subsumes_predicate<R, S1, S2>());
+
+// clang-format off
+template<class F, class T, class U>
+requires std::relation<F, T, T> && std::relation<F, U, U>
+[[nodiscard]] constexpr bool check_relation_subsumes_itself() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::relation<F, T, U>
+[[nodiscard]] constexpr bool check_relation_subsumes_itself() {
+  return true;
+}
+// clang-format on
+
+static_assert(check_relation_subsumes_itself<int (*)(int, double), int, int>());
+static_assert(check_relation_subsumes_itself<R, S1, S1>());

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp
new file mode 100644
index 0000000000000..08351dc2e7700
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.compile.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept strict_weak_order;
+
+#include <concepts>
+
+static_assert(std::strict_weak_order<bool(int, int), int, int>);
+static_assert(std::strict_weak_order<bool(int, int), double, double>);
+static_assert(std::strict_weak_order<bool(int, double), double, double>);
+
+static_assert(!std::strict_weak_order<bool (*)(), int, double>);
+static_assert(!std::strict_weak_order<bool (*)(int), int, double>);
+static_assert(!std::strict_weak_order<bool (*)(double), int, double>);
+
+static_assert(!std::strict_weak_order<bool(double, double*), double, double*>);
+static_assert(!std::strict_weak_order<bool(int&, int&), double&, double&>);
+
+struct S1 {};
+static_assert(std::strict_weak_order<bool (S1::*)(S1*), S1*, S1*>);
+static_assert(std::strict_weak_order<bool (S1::*)(S1&), S1&, S1&>);
+
+struct S2 {};
+
+struct P1 {
+  bool operator()(S1, S1) const;
+};
+static_assert(std::strict_weak_order<P1, S1, S1>);
+
+struct P2 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+};
+static_assert(!std::strict_weak_order<P2, S1, S2>);
+
+struct P3 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+};
+static_assert(!std::strict_weak_order<P3, S1, S2>);
+
+struct P4 {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+static_assert(std::strict_weak_order<P4, S1, S2>);

diff  --git a/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp
new file mode 100644
index 0000000000000..34574f649a3fe
--- /dev/null
+++ b/libcxx/test/std/concepts/concepts.callable/concept.strictweakorder/strict_weak_order.subsumption.compile.pass.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class F, class... Args>
+// concept strict_weak_order;
+
+#include <concepts>
+
+struct S1 {};
+struct S2 {};
+
+struct R {
+  bool operator()(S1, S1) const;
+  bool operator()(S1, S2) const;
+  bool operator()(S2, S1) const;
+  bool operator()(S2, S2) const;
+};
+
+// clang-format off
+template<class F, class T, class U>
+requires std::relation<F, T, U>
+[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::strict_weak_order<F, T, U> && true
+[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_relation() {
+  return true;
+}
+// clang-format on
+
+static_assert(
+    check_strict_weak_order_subsumes_relation<int (*)(int, int), int, int>());
+static_assert(check_strict_weak_order_subsumes_relation<int (*)(int, double),
+                                                        int, double>());
+static_assert(check_strict_weak_order_subsumes_relation<R, S1, S1>());
+static_assert(check_strict_weak_order_subsumes_relation<R, S1, S2>());
+
+// clang-format off
+template<class F, class T, class U>
+requires std::relation<F, T, U> && true
+[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() {
+  return true;
+}
+
+template<class F, class T, class U>
+requires std::strict_weak_order<F, T, U>
+[[nodiscard]] constexpr bool check_relation_subsumes_strict_weak_order() {
+  return false;
+}
+// clang-format on
+
+static_assert(
+    check_relation_subsumes_strict_weak_order<int (*)(int, int), int, int>());
+static_assert(check_relation_subsumes_strict_weak_order<int (*)(int, double),
+                                                        int, double>());
+static_assert(check_relation_subsumes_strict_weak_order<R, S1, S1>());
+static_assert(check_relation_subsumes_strict_weak_order<R, S1, S2>());
+
+// clang-format off
+template<class F, class T, class U>
+requires std::strict_weak_order<F, T, T> && std::strict_weak_order<F, U, U>
+[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() {
+  return false;
+}
+
+template<class F, class T, class U>
+requires std::strict_weak_order<F, T, U>
+[[nodiscard]] constexpr bool check_strict_weak_order_subsumes_itself() {
+  return true;
+}
+// clang-format on
+
+static_assert(
+    check_strict_weak_order_subsumes_itself<int (*)(int, int), int, int>());
+static_assert(check_strict_weak_order_subsumes_itself<R, S1, S1>());


        


More information about the libcxx-commits mailing list