[libcxx-commits] [libcxx] [libc++][test] Test SFINAE for `optional`'s operators in C++17 (PR #221643)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Sep 7 18:32:23 PDT 2026
https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/221643
>From 1a5f58448edbfd501ce55f064e865ad303b04596 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Mon, 7 Sep 2026 13:52:43 +0800
Subject: [PATCH 1/2] [libc++][test] Test SFINAE for `optional`'s operators in
C++17
We have been intentionally constraining `optional`'s comparison
operators since C++17, so it is probably better to test the constraints
in C++17 mode. Given the constraints are standardized only since C++26
(via P2944R3), `LIBCPP_STATIC_ASSERT` is used in old modes.
In order to do this, `test_comparisons.h` is reworked to expose
`NonComparable` and `EqualityComparable` in pre-C++20 modes, and a new
type `TotallyOrdered` is invented as a replacement of
`ThreeWayComparable` in old modes.
As drive-by, also switches to use `// REQUIRES: std-at-least-c++17` in
touched test files, and adds previously missed includes of
`<type_traits>`.
---
.../optional.comp_with_t/equal.pass.cpp | 35 ++--
.../optional.comp_with_t/greater.pass.cpp | 35 ++--
.../greater_equal.pass.cpp | 35 ++--
.../optional.comp_with_t/less_equal.pass.cpp | 35 ++--
.../optional.comp_with_t/less_than.pass.cpp | 35 ++--
.../optional.comp_with_t/not_equal.pass.cpp | 35 ++--
.../optional/optional.relops/equal.pass.cpp | 20 ++-
.../optional.relops/greater_equal.pass.cpp | 18 +-
.../optional.relops/greater_than.pass.cpp | 19 ++-
.../optional.relops/less_equal.pass.cpp | 18 +-
.../optional.relops/less_than.pass.cpp | 18 +-
.../optional.relops/not_equal.pass.cpp | 20 ++-
libcxx/test/support/test_comparisons.h | 156 +++++++++++++++---
13 files changed, 310 insertions(+), 169 deletions(-)
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp
index 99813dae89031..d33caab090b3b 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator==(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,7 +37,7 @@ constexpr bool operator==(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_eq(const T& t, const U& u) {
- if constexpr (requires { t == u; })
+ if constexpr (HasOperatorEqual<const T, const U>)
return t == u;
else
return {};
@@ -40,25 +45,23 @@ constexpr std::optional<bool> try_cmp_eq(const T& t, const U& u) {
// Test SFINAE.
-static_assert(HasOperatorEqual<int, std::optional<int>>);
-static_assert(HasOperatorEqual<int, std::optional<EqualityComparable>>);
-static_assert(HasOperatorEqual<EqualityComparable, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<int, std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<int, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<EqualityComparable, std::optional<EqualityComparable>>);
-static_assert(!HasOperatorEqual<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorEqual<NonComparable, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<NonComparable, std::optional<EqualityComparable>>);
-static_assert(HasOperatorEqual<std::optional<int>, int>);
-static_assert(HasOperatorEqual<std::optional<EqualityComparable>, int>);
-static_assert(HasOperatorEqual<std::optional<EqualityComparable>, EqualityComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<int>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<EqualityComparable>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<EqualityComparable>, EqualityComparable>);
-static_assert(!HasOperatorEqual<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorEqual<std::optional<EqualityComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<std::optional<EqualityComparable>, NonComparable>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_eq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_eq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_eq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_eq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp
index a945cf4b54002..a4a3f0922b8b6 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator>(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,32 +37,30 @@ constexpr bool operator>(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_gt(const T& t, const U& u) {
- if constexpr (requires { t > u; })
+ if constexpr (HasOperatorGreaterThan<const T, const U>)
return t > u;
else
return {};
}
// Test SFINAE.
-static_assert(HasOperatorGreaterThan<std::optional<ThreeWayComparable>, int>);
-static_assert(HasOperatorGreaterThan<std::optional<ThreeWayComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<std::optional<TotallyOrdered>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<std::optional<TotallyOrdered>, TotallyOrdered>);
-static_assert(!HasOperatorGreaterThan<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorGreaterThan<std::optional<ThreeWayComparable>, NonComparable>);
-static_assert(!HasOperatorGreaterThan<std::optional<NonComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<TotallyOrdered>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<NonComparable>, TotallyOrdered>);
-static_assert(HasOperatorGreaterThan<int, std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorGreaterThan<ThreeWayComparable, std::optional<ThreeWayComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<int, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<TotallyOrdered, std::optional<TotallyOrdered>>);
-static_assert(!HasOperatorGreaterThan<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorGreaterThan<NonComparable, std::optional<ThreeWayComparable>>);
-static_assert(!HasOperatorGreaterThan<ThreeWayComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<NonComparable, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<TotallyOrdered, std::optional<NonComparable>>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_gt(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_gt(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_gt(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_gt(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp
index 8e18568bfe6d7..4cb4fb6092376 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator>=(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,32 +37,30 @@ constexpr bool operator>=(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_gteq(const T& t, const U& u) {
- if constexpr (requires { t >= u; })
+ if constexpr (HasOperatorGreaterThanEqual<const T, const U>)
return t >= u;
else
return {};
}
// Test SFINAE.
-static_assert(HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>, int>);
-static_assert(HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>, TotallyOrdered>);
-static_assert(!HasOperatorGreaterThanEqual<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>, NonComparable>);
-static_assert(!HasOperatorGreaterThanEqual<std::optional<NonComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<NonComparable>, TotallyOrdered>);
-static_assert(HasOperatorGreaterThanEqual<int, std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorGreaterThanEqual<ThreeWayComparable, std::optional<ThreeWayComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<int, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<TotallyOrdered, std::optional<TotallyOrdered>>);
-static_assert(!HasOperatorGreaterThanEqual<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorGreaterThanEqual<NonComparable, std::optional<ThreeWayComparable>>);
-static_assert(!HasOperatorGreaterThanEqual<ThreeWayComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<NonComparable, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<TotallyOrdered, std::optional<NonComparable>>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_gteq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_gteq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_gteq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_gteq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp
index c937d7b2a5faf..81bd00bbba579 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator<=(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,32 +37,30 @@ constexpr bool operator<=(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_lteq(const T& t, const U& u) {
- if constexpr (requires { t <= u; })
+ if constexpr (HasOperatorLessThanEqual<const T, const U>)
return t <= u;
else
return {};
}
// Test SFINAE.
-static_assert(HasOperatorLessThanEqual<std::optional<ThreeWayComparable>, int>);
-static_assert(HasOperatorLessThanEqual<std::optional<ThreeWayComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<std::optional<TotallyOrdered>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<std::optional<TotallyOrdered>, TotallyOrdered>);
-static_assert(!HasOperatorLessThanEqual<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorLessThanEqual<std::optional<ThreeWayComparable>, NonComparable>);
-static_assert(!HasOperatorLessThanEqual<std::optional<NonComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<TotallyOrdered>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<NonComparable>, TotallyOrdered>);
-static_assert(HasOperatorLessThanEqual<int, std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorLessThanEqual<ThreeWayComparable, std::optional<ThreeWayComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<int, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<TotallyOrdered, std::optional<TotallyOrdered>>);
-static_assert(!HasOperatorLessThanEqual<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorLessThanEqual<NonComparable, std::optional<ThreeWayComparable>>);
-static_assert(!HasOperatorLessThanEqual<ThreeWayComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<NonComparable, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<TotallyOrdered, std::optional<NonComparable>>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_lteq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_lteq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_lteq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_lteq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{true});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp
index 9a1aa0c65f272..5ffed14348345 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator<(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,32 +37,30 @@ constexpr bool operator<(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_lt(const T& t, const U& u) {
- if constexpr (requires { t < u; })
+ if constexpr (HasOperatorLessThan<const T, const U>)
return t < u;
else
return {};
}
// Test SFINAE.
-static_assert(HasOperatorLessThan<std::optional<ThreeWayComparable>, int>);
-static_assert(HasOperatorLessThan<std::optional<ThreeWayComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<std::optional<TotallyOrdered>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<std::optional<TotallyOrdered>, TotallyOrdered>);
-static_assert(!HasOperatorLessThan<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorLessThan<std::optional<ThreeWayComparable>, NonComparable>);
-static_assert(!HasOperatorLessThan<std::optional<NonComparable>, ThreeWayComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<TotallyOrdered>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<NonComparable>, TotallyOrdered>);
-static_assert(HasOperatorLessThan<int, std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorLessThan<ThreeWayComparable, std::optional<ThreeWayComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<int, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<TotallyOrdered, std::optional<TotallyOrdered>>);
-static_assert(!HasOperatorLessThan<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorLessThan<NonComparable, std::optional<ThreeWayComparable>>);
-static_assert(!HasOperatorLessThan<ThreeWayComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<NonComparable, std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<TotallyOrdered, std::optional<NonComparable>>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_lt(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_lt(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_lt(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_lt(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp
index e7940b9b421a3..8c9e6e2d73e9f 100644
--- a/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp
@@ -6,18 +6,23 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
// template <class T, class U> constexpr bool operator!=(const U& v, const optional<T>& x);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
struct tester {};
@@ -32,7 +37,7 @@ constexpr bool operator!=(const T& t, const tester& a) {
template <class T, class U>
constexpr std::optional<bool> try_cmp_neq(const T& t, const U& u) {
- if constexpr (requires { t != u; })
+ if constexpr (HasOperatorNotEqual<const T, const U>)
return t != u;
else
return {};
@@ -40,25 +45,23 @@ constexpr std::optional<bool> try_cmp_neq(const T& t, const U& u) {
// Test SFINAE.
-static_assert(HasOperatorNotEqual<int, std::optional<int>>);
-static_assert(HasOperatorNotEqual<int, std::optional<EqualityComparable>>);
-static_assert(HasOperatorNotEqual<EqualityComparable, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<int, std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<int, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<EqualityComparable, std::optional<EqualityComparable>>);
-static_assert(!HasOperatorNotEqual<NonComparable, std::optional<NonComparable>>);
-static_assert(!HasOperatorNotEqual<NonComparable, std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<NonComparable, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<NonComparable, std::optional<EqualityComparable>>);
-static_assert(HasOperatorNotEqual<std::optional<int>, int>);
-static_assert(HasOperatorNotEqual<std::optional<EqualityComparable>, int>);
-static_assert(HasOperatorNotEqual<std::optional<EqualityComparable>, EqualityComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<int>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<EqualityComparable>, int>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<EqualityComparable>, EqualityComparable>);
-static_assert(!HasOperatorNotEqual<std::optional<NonComparable>, NonComparable>);
-static_assert(!HasOperatorNotEqual<std::optional<EqualityComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<std::optional<NonComparable>, NonComparable>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<std::optional<EqualityComparable>, NonComparable>);
// LWG4072: avoid ambiguity with optional's own comparison operators
-static_assert(try_cmp_neq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
-static_assert(try_cmp_neq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_neq(std::optional<int>{}, std::optional<tester>{}) == std::optional<bool>{});
+STATIC_ASSERT_OPTIONAL_CMP(try_cmp_neq(std::optional<int>{}, std::optional<int>{}) == std::optional<bool>{false});
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp
index 6915b604d4ef4..96a2c1d6acdb7 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp
@@ -6,30 +6,32 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
+#include <cassert>
#include <optional>
#include <type_traits>
-#include <cassert>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorEqual<std::optional<int>>);
-static_assert(HasOperatorEqual<std::optional<EqualityComparable>>);
-static_assert(HasOperatorEqual<std::optional<EqualityComparable>, std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorEqual<std::optional<EqualityComparable>, std::optional<int>>);
-static_assert(!HasOperatorEqual<std::optional<NonComparable>>);
-static_assert(!HasOperatorEqual<std::optional<EqualityComparable>, std::optional<NonComparable>>);
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorEqual<std::optional<EqualityComparable>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp
index d14e7df6abc80..845912eb5deb0 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator>= (const optional<T>& x, const optional<U>& y);
@@ -17,16 +17,18 @@
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>, std::optional<int>>);
-
-static_assert(!HasOperatorGreaterThanEqual<std::optional<NonComparable>>);
-static_assert(!HasOperatorGreaterThanEqual<std::optional<EqualityComparable>>);
-static_assert(!HasOperatorGreaterThanEqual<std::optional<ThreeWayComparable>, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>, std::optional<int>>);
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThanEqual<std::optional<TotallyOrdered>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp
index f19ea23e8ae78..ff92a3362fa06 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp
@@ -6,27 +6,30 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator> (const optional<T>& x, const optional<U>& y);
#include <optional>
+#include <type_traits>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorGreaterThan<std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorGreaterThan<std::optional<ThreeWayComparable>, std::optional<int>>);
-
-static_assert(!HasOperatorGreaterThan<std::optional<NonComparable>>);
-static_assert(!HasOperatorGreaterThan<std::optional<EqualityComparable>>);
-static_assert(!HasOperatorGreaterThan<std::optional<ThreeWayComparable>, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorGreaterThan<std::optional<TotallyOrdered>, std::optional<int>>);
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorGreaterThan<std::optional<TotallyOrdered>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp
index bd81a79f1265e..aaee72229d2ef 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator<= (const optional<T>& x, const optional<U>& y);
@@ -17,16 +17,18 @@
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorLessThanEqual<std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorLessThanEqual<std::optional<ThreeWayComparable>, std::optional<int>>);
-
-static_assert(!HasOperatorLessThanEqual<std::optional<NonComparable>>);
-static_assert(!HasOperatorLessThanEqual<std::optional<EqualityComparable>>);
-static_assert(!HasOperatorLessThanEqual<std::optional<ThreeWayComparable>, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThanEqual<std::optional<TotallyOrdered>, std::optional<int>>);
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThanEqual<std::optional<TotallyOrdered>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp
index c87bfd6f73e54..b5e8a85aa5e50 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator< (const optional<T>& x, const optional<U>& y);
@@ -17,16 +17,18 @@
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorLessThan<std::optional<ThreeWayComparable>>);
-static_assert(HasOperatorLessThan<std::optional<ThreeWayComparable>, std::optional<int>>);
-
-static_assert(!HasOperatorLessThan<std::optional<NonComparable>>);
-static_assert(!HasOperatorLessThan<std::optional<EqualityComparable>>);
-static_assert(!HasOperatorLessThan<std::optional<ThreeWayComparable>, std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<std::optional<TotallyOrdered>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorLessThan<std::optional<TotallyOrdered>, std::optional<int>>);
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorLessThan<std::optional<TotallyOrdered>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp
index 1b7d2621c9193..6ca2d4818a63a 100644
--- a/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp
@@ -6,30 +6,32 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <optional>
// template <class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
+#include <cassert>
#include <optional>
#include <type_traits>
-#include <cassert>
#include "test_comparisons.h"
#include "test_macros.h"
#if TEST_STD_VER >= 26
+# define STATIC_ASSERT_OPTIONAL_CMP static_assert
+#else
+# define STATIC_ASSERT_OPTIONAL_CMP LIBCPP_STATIC_ASSERT
+#endif
// Test SFINAE.
-static_assert(HasOperatorNotEqual<std::optional<int>>);
-static_assert(HasOperatorNotEqual<std::optional<EqualityComparable>>);
-static_assert(HasOperatorNotEqual<std::optional<EqualityComparable>, std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<int>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<EqualityComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(HasOperatorNotEqual<std::optional<EqualityComparable>, std::optional<int>>);
-static_assert(!HasOperatorNotEqual<std::optional<NonComparable>>);
-static_assert(!HasOperatorNotEqual<std::optional<EqualityComparable>, std::optional<NonComparable>>);
-
-#endif
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<std::optional<NonComparable>>);
+STATIC_ASSERT_OPTIONAL_CMP(!HasOperatorNotEqual<std::optional<EqualityComparable>, std::optional<NonComparable>>);
using std::optional;
diff --git a/libcxx/test/support/test_comparisons.h b/libcxx/test/support/test_comparisons.h
index 9d8bf910a2ebc..41e03720a8cce 100644
--- a/libcxx/test/support/test_comparisons.h
+++ b/libcxx/test/support/test_comparisons.h
@@ -288,29 +288,6 @@ concept HasOperatorNotEqual = requires(T1 t1, T2 t2) { t1 != t2; };
template <typename T1, typename T2 = T1>
concept HasOperatorSpaceship = requires(T1 t1, T2 t2) { t1 <=> t2; };
-struct NonComparable {};
-static_assert(!std::equality_comparable<NonComparable>);
-static_assert(!HasOperatorEqual<NonComparable>);
-static_assert(!HasOperatorGreaterThan<NonComparable>);
-static_assert(!HasOperatorGreaterThanEqual<NonComparable>);
-static_assert(!HasOperatorLessThan<NonComparable>);
-static_assert(!HasOperatorLessThanEqual<NonComparable>);
-static_assert(!HasOperatorNotEqual<NonComparable>);
-static_assert(!HasOperatorSpaceship<NonComparable>);
-
-class EqualityComparable {
-public:
- constexpr EqualityComparable(int value) : value_{value} {};
-
- friend constexpr bool operator==(const EqualityComparable&, const EqualityComparable&) noexcept = default;
-
-private:
- int value_;
-};
-static_assert(std::equality_comparable<EqualityComparable>);
-static_assert(HasOperatorEqual<EqualityComparable>);
-static_assert(HasOperatorNotEqual<EqualityComparable>);
-
class ThreeWayComparable {
public:
constexpr ThreeWayComparable(int value) : value_{value} {};
@@ -349,6 +326,139 @@ struct ImplicitBool {
constexpr ImplicitBool operator==(ImplicitBool::E1 lhs, ImplicitBool::E2 rhs) { return {lhs.x == rhs.y}; }
+#elif TEST_STD_VER >= 14
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorEqual = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorEqual<T1, T2, decltype((void)(std::declval<T1&>() == std::declval<T2&>()))> = true;
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorGreaterThan = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorGreaterThan<T1, T2, decltype((void)(std::declval<T1&>() > std::declval<T2&>()))> = true;
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorGreaterThanEqual = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorGreaterThanEqual<T1, T2, decltype((void)(std::declval<T1&>() >= std::declval<T2&>()))> = true;
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorLessThan = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorLessThan<T1, T2, decltype((void)(std::declval<T1&>() < std::declval<T2&>()))> = true;
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorLessThanEqual = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorLessThanEqual<T1, T2, decltype((void)(std::declval<T1&>() <= std::declval<T2&>()))> = true;
+
+template <typename T1, typename T2 = T1, typename = void>
+constexpr bool HasOperatorNotEqual = false;
+template <typename T1, typename T2>
+constexpr bool HasOperatorNotEqual<T1, T2, decltype((void)(std::declval<T1&>() != std::declval<T2&>()))> = true;
+
+#endif // TEST_STD_VER >= 20
+
+struct NonComparable {};
+
+class EqualityComparable {
+public:
+ TEST_CONSTEXPR EqualityComparable(int value) : value_(value) {};
+
+#if TEST_STD_VER >= 20
+ friend constexpr bool operator==(const EqualityComparable&, const EqualityComparable&) noexcept = default;
+#else
+ friend TEST_CONSTEXPR bool operator==(const EqualityComparable& lhs, const EqualityComparable& rhs) TEST_NOEXCEPT {
+ return lhs.value_ == rhs.value_;
+ }
+
+ friend TEST_CONSTEXPR bool operator!=(const EqualityComparable& lhs, const EqualityComparable& rhs) TEST_NOEXCEPT {
+ return !(lhs == rhs);
+ }
+#endif
+
+private:
+ int value_;
+};
+
+class TotallyOrdered {
+public:
+ TEST_CONSTEXPR TotallyOrdered(int value) : value_(value) {};
+
+#if TEST_STD_VER >= 20
+ friend constexpr bool operator==(const TotallyOrdered&, const TotallyOrdered&) noexcept = default;
+#else
+ friend TEST_CONSTEXPR bool operator==(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return lhs.value_ == rhs.value_;
+ }
+
+ friend TEST_CONSTEXPR bool operator!=(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return !(lhs == rhs);
+ }
+#endif
+
+ friend TEST_CONSTEXPR bool operator<(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return lhs.value_ < rhs.value_;
+ }
+
+ friend TEST_CONSTEXPR bool operator>(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return rhs < lhs;
+ }
+
+ friend TEST_CONSTEXPR bool operator<=(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return !(rhs < lhs);
+ }
+
+ friend TEST_CONSTEXPR bool operator>=(const TotallyOrdered& lhs, const TotallyOrdered& rhs) TEST_NOEXCEPT {
+ return !(lhs < rhs);
+ }
+
+private:
+ int value_;
+};
+
+#if TEST_STD_VER >= 14
+
+static_assert(!HasOperatorEqual<NonComparable>, "");
+static_assert(!HasOperatorGreaterThan<NonComparable>, "");
+static_assert(!HasOperatorGreaterThanEqual<NonComparable>, "");
+static_assert(!HasOperatorLessThan<NonComparable>, "");
+static_assert(!HasOperatorLessThanEqual<NonComparable>, "");
+static_assert(!HasOperatorNotEqual<NonComparable>, "");
+
+static_assert(HasOperatorEqual<EqualityComparable>, "");
+static_assert(HasOperatorNotEqual<EqualityComparable>, "");
+static_assert(!HasOperatorGreaterThanEqual<EqualityComparable>, "");
+static_assert(!HasOperatorLessThan<EqualityComparable>, "");
+static_assert(!HasOperatorLessThanEqual<EqualityComparable>, "");
+
+static_assert(HasOperatorEqual<TotallyOrdered>, "");
+static_assert(HasOperatorNotEqual<TotallyOrdered>, "");
+static_assert(HasOperatorGreaterThanEqual<TotallyOrdered>, "");
+static_assert(HasOperatorLessThan<TotallyOrdered>, "");
+static_assert(HasOperatorLessThanEqual<TotallyOrdered>, "");
+static_assert(HasOperatorNotEqual<TotallyOrdered>, "");
+
+#endif // TEST_STD_VER >= 14
+
+#if TEST_STD_VER >= 20
+
+static_assert(!std::equality_comparable<NonComparable>);
+static_assert(!std::totally_ordered<NonComparable>);
+static_assert(!std::three_way_comparable<NonComparable>);
+static_assert(!HasOperatorSpaceship<NonComparable>);
+
+static_assert(std::equality_comparable<EqualityComparable>);
+static_assert(!std::totally_ordered<EqualityComparable>);
+static_assert(!std::three_way_comparable<EqualityComparable>);
+static_assert(!HasOperatorSpaceship<EqualityComparable>);
+
+static_assert(std::equality_comparable<TotallyOrdered>);
+static_assert(std::totally_ordered<TotallyOrdered>);
+static_assert(!std::three_way_comparable<TotallyOrdered>);
+static_assert(!HasOperatorSpaceship<TotallyOrdered>);
+
#endif // TEST_STD_VER >= 20
#endif // TEST_COMPARISONS_H
>From 393e9537ae25a6396f37b05e9ea317dfc67beccc Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Tue, 8 Sep 2026 09:32:02 +0800
Subject: [PATCH 2/2] Reorder definitions in `test_comparisons.h`
And expose `ImplicitBool` to C++11 mode.
---
libcxx/test/support/test_comparisons.h | 200 ++++++++++++++-----------
1 file changed, 112 insertions(+), 88 deletions(-)
diff --git a/libcxx/test/support/test_comparisons.h b/libcxx/test/support/test_comparisons.h
index 41e03720a8cce..bde041354d0e4 100644
--- a/libcxx/test/support/test_comparisons.h
+++ b/libcxx/test/support/test_comparisons.h
@@ -241,33 +241,6 @@ struct LessAndEqComp {
#if TEST_STD_VER >= 20
-struct StrongOrder {
- int value;
- constexpr StrongOrder(int v) : value(v) {}
- friend std::strong_ordering operator<=>(StrongOrder, StrongOrder) = default;
-};
-
-struct WeakOrder {
- int value;
- constexpr WeakOrder(int v) : value(v) {}
- friend std::weak_ordering operator<=>(WeakOrder, WeakOrder) = default;
-};
-
-struct PartialOrder {
- int value;
- constexpr PartialOrder(int v) : value(v) {}
- friend constexpr std::partial_ordering operator<=>(PartialOrder lhs, PartialOrder rhs) {
- if (lhs.value == std::numeric_limits<int>::min() || rhs.value == std::numeric_limits<int>::min())
- return std::partial_ordering::unordered;
- if (lhs.value == std::numeric_limits<int>::max() || rhs.value == std::numeric_limits<int>::max())
- return std::partial_ordering::unordered;
- return lhs.value <=> rhs.value;
- }
- friend constexpr bool operator==(PartialOrder lhs, PartialOrder rhs) {
- return (lhs <=> rhs) == std::partial_ordering::equivalent;
- }
-};
-
template <typename T1, typename T2 = T1>
concept HasOperatorEqual = requires(T1 t1, T2 t2) { t1 == t2; };
@@ -288,44 +261,6 @@ concept HasOperatorNotEqual = requires(T1 t1, T2 t2) { t1 != t2; };
template <typename T1, typename T2 = T1>
concept HasOperatorSpaceship = requires(T1 t1, T2 t2) { t1 <=> t2; };
-class ThreeWayComparable {
-public:
- constexpr ThreeWayComparable(int value) : value_{value} {};
-
- friend constexpr bool operator==(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
- friend constexpr std::strong_ordering
- operator<=>(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
-
-private:
- int value_;
-};
-static_assert(std::equality_comparable<ThreeWayComparable>);
-static_assert(std::three_way_comparable<ThreeWayComparable>);
-static_assert(HasOperatorEqual<ThreeWayComparable>);
-static_assert(HasOperatorGreaterThan<ThreeWayComparable>);
-static_assert(HasOperatorGreaterThanEqual<ThreeWayComparable>);
-static_assert(HasOperatorLessThan<ThreeWayComparable>);
-static_assert(HasOperatorLessThanEqual<ThreeWayComparable>);
-static_assert(HasOperatorNotEqual<ThreeWayComparable>);
-static_assert(HasOperatorSpaceship<ThreeWayComparable>);
-
-// LWG4366: Heterogeneous comparison of expected may be ill-formed
-struct ImplicitBool {
- bool val;
- constexpr operator bool() const { return val; };
- constexpr explicit operator bool() = delete;
-
- struct E1 {
- int x;
- };
-
- struct E2 {
- int y;
- };
-};
-
-constexpr ImplicitBool operator==(ImplicitBool::E1 lhs, ImplicitBool::E2 rhs) { return {lhs.x == rhs.y}; }
-
#elif TEST_STD_VER >= 14
template <typename T1, typename T2 = T1, typename = void>
@@ -362,6 +297,26 @@ constexpr bool HasOperatorNotEqual<T1, T2, decltype((void)(std::declval<T1&>() !
struct NonComparable {};
+#if TEST_STD_VER >= 14
+
+static_assert(!HasOperatorEqual<NonComparable>, "");
+static_assert(!HasOperatorGreaterThan<NonComparable>, "");
+static_assert(!HasOperatorGreaterThanEqual<NonComparable>, "");
+static_assert(!HasOperatorLessThan<NonComparable>, "");
+static_assert(!HasOperatorLessThanEqual<NonComparable>, "");
+static_assert(!HasOperatorNotEqual<NonComparable>, "");
+
+#endif // TEST_STD_VER >= 14
+
+#if TEST_STD_VER >= 20
+
+static_assert(!std::equality_comparable<NonComparable>);
+static_assert(!std::totally_ordered<NonComparable>);
+static_assert(!std::three_way_comparable<NonComparable>);
+static_assert(!HasOperatorSpaceship<NonComparable>);
+
+#endif // TEST_STD_VER >= 20
+
class EqualityComparable {
public:
TEST_CONSTEXPR EqualityComparable(int value) : value_(value) {};
@@ -382,6 +337,25 @@ class EqualityComparable {
int value_;
};
+#if TEST_STD_VER >= 14
+
+static_assert(HasOperatorEqual<EqualityComparable>, "");
+static_assert(HasOperatorNotEqual<EqualityComparable>, "");
+static_assert(!HasOperatorGreaterThanEqual<EqualityComparable>, "");
+static_assert(!HasOperatorLessThan<EqualityComparable>, "");
+static_assert(!HasOperatorLessThanEqual<EqualityComparable>, "");
+
+#endif // TEST_STD_VER >= 14
+
+#if TEST_STD_VER >= 20
+
+static_assert(std::equality_comparable<EqualityComparable>);
+static_assert(!std::totally_ordered<EqualityComparable>);
+static_assert(!std::three_way_comparable<EqualityComparable>);
+static_assert(!HasOperatorSpaceship<EqualityComparable>);
+
+#endif // TEST_STD_VER >= 20
+
class TotallyOrdered {
public:
TEST_CONSTEXPR TotallyOrdered(int value) : value_(value) {};
@@ -420,19 +394,6 @@ class TotallyOrdered {
#if TEST_STD_VER >= 14
-static_assert(!HasOperatorEqual<NonComparable>, "");
-static_assert(!HasOperatorGreaterThan<NonComparable>, "");
-static_assert(!HasOperatorGreaterThanEqual<NonComparable>, "");
-static_assert(!HasOperatorLessThan<NonComparable>, "");
-static_assert(!HasOperatorLessThanEqual<NonComparable>, "");
-static_assert(!HasOperatorNotEqual<NonComparable>, "");
-
-static_assert(HasOperatorEqual<EqualityComparable>, "");
-static_assert(HasOperatorNotEqual<EqualityComparable>, "");
-static_assert(!HasOperatorGreaterThanEqual<EqualityComparable>, "");
-static_assert(!HasOperatorLessThan<EqualityComparable>, "");
-static_assert(!HasOperatorLessThanEqual<EqualityComparable>, "");
-
static_assert(HasOperatorEqual<TotallyOrdered>, "");
static_assert(HasOperatorNotEqual<TotallyOrdered>, "");
static_assert(HasOperatorGreaterThanEqual<TotallyOrdered>, "");
@@ -444,16 +405,6 @@ static_assert(HasOperatorNotEqual<TotallyOrdered>, "");
#if TEST_STD_VER >= 20
-static_assert(!std::equality_comparable<NonComparable>);
-static_assert(!std::totally_ordered<NonComparable>);
-static_assert(!std::three_way_comparable<NonComparable>);
-static_assert(!HasOperatorSpaceship<NonComparable>);
-
-static_assert(std::equality_comparable<EqualityComparable>);
-static_assert(!std::totally_ordered<EqualityComparable>);
-static_assert(!std::three_way_comparable<EqualityComparable>);
-static_assert(!HasOperatorSpaceship<EqualityComparable>);
-
static_assert(std::equality_comparable<TotallyOrdered>);
static_assert(std::totally_ordered<TotallyOrdered>);
static_assert(!std::three_way_comparable<TotallyOrdered>);
@@ -461,4 +412,77 @@ static_assert(!HasOperatorSpaceship<TotallyOrdered>);
#endif // TEST_STD_VER >= 20
+#if TEST_STD_VER >= 20
+
+struct StrongOrder {
+ int value;
+ constexpr StrongOrder(int v) : value(v) {}
+ friend std::strong_ordering operator<=>(StrongOrder, StrongOrder) = default;
+};
+
+struct WeakOrder {
+ int value;
+ constexpr WeakOrder(int v) : value(v) {}
+ friend std::weak_ordering operator<=>(WeakOrder, WeakOrder) = default;
+};
+
+struct PartialOrder {
+ int value;
+ constexpr PartialOrder(int v) : value(v) {}
+ friend constexpr std::partial_ordering operator<=>(PartialOrder lhs, PartialOrder rhs) {
+ if (lhs.value == std::numeric_limits<int>::min() || rhs.value == std::numeric_limits<int>::min())
+ return std::partial_ordering::unordered;
+ if (lhs.value == std::numeric_limits<int>::max() || rhs.value == std::numeric_limits<int>::max())
+ return std::partial_ordering::unordered;
+ return lhs.value <=> rhs.value;
+ }
+ friend constexpr bool operator==(PartialOrder lhs, PartialOrder rhs) {
+ return (lhs <=> rhs) == std::partial_ordering::equivalent;
+ }
+};
+
+class ThreeWayComparable {
+public:
+ constexpr ThreeWayComparable(int value) : value_{value} {};
+
+ friend constexpr bool operator==(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
+ friend constexpr std::strong_ordering
+ operator<=>(const ThreeWayComparable&, const ThreeWayComparable&) noexcept = default;
+
+private:
+ int value_;
+};
+static_assert(std::equality_comparable<ThreeWayComparable>);
+static_assert(std::three_way_comparable<ThreeWayComparable>);
+static_assert(HasOperatorEqual<ThreeWayComparable>);
+static_assert(HasOperatorGreaterThan<ThreeWayComparable>);
+static_assert(HasOperatorGreaterThanEqual<ThreeWayComparable>);
+static_assert(HasOperatorLessThan<ThreeWayComparable>);
+static_assert(HasOperatorLessThanEqual<ThreeWayComparable>);
+static_assert(HasOperatorNotEqual<ThreeWayComparable>);
+static_assert(HasOperatorSpaceship<ThreeWayComparable>);
+
+#endif // TEST_STD_VER >= 20
+
+#if TEST_STD_VER >= 11
+
+// LWG4366: Heterogeneous comparison of expected may be ill-formed
+struct ImplicitBool {
+ bool val;
+ constexpr operator bool() const { return val; };
+ constexpr explicit operator bool() = delete;
+
+ struct E1 {
+ int x;
+ };
+
+ struct E2 {
+ int y;
+ };
+};
+
+constexpr ImplicitBool operator==(ImplicitBool::E1 lhs, ImplicitBool::E2 rhs) { return {lhs.x == rhs.y}; }
+
+#endif // TEST_STD_VER >= 11
+
#endif // TEST_COMPARISONS_H
More information about the libcxx-commits
mailing list