[libcxx-commits] [libcxx] WIP [libc++]P2944R3: Constrained comparisions - `variant` and `tuple` (PR #141396)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jun 4 20:49:13 PDT 2025


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/141396

>From a7517fdb7493d8c57c836099bccacc51cba691c4 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 11 May 2025 01:48:15 +0300
Subject: [PATCH 1/5] [libc++] P2944R3: Constrained comparisions - optional and
 reference_wrapper

Implements `variant`: https://wg21.link/P2944R3

Closes #136769
---
 libcxx/include/variant                        | 31 +++++++++
 .../variant/variant.relops/relops.pass.cpp    | 43 ++++++++++++
 libcxx/test/support/test_comparisons.h        | 66 ++++++++++++++++++-
 3 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/variant b/libcxx/include/variant
index bf611aec704ca..8dc3e9fb0f93b 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -242,6 +242,7 @@ namespace std {
 #  include <__type_traits/is_assignable.h>
 #  include <__type_traits/is_constructible.h>
 #  include <__type_traits/is_convertible.h>
+#  include <__type_traits/is_core_convertible.h>
 #  include <__type_traits/is_destructible.h>
 #  include <__type_traits/is_nothrow_assignable.h>
 #  include <__type_traits/is_nothrow_constructible.h>
@@ -1453,6 +1454,11 @@ struct __convert_to_bool {
 };
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t == __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__lhs.index() != __rhs.index())
@@ -1485,6 +1491,11 @@ operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
 #    endif // _LIBCPP_STD_VER >= 20
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t != __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__lhs.index() != __rhs.index())
@@ -1495,6 +1506,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs,
 }
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t < __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__rhs.valueless_by_exception())
@@ -1509,6 +1525,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs,
 }
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t > __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__lhs.valueless_by_exception())
@@ -1523,6 +1544,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs,
 }
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t <= __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__lhs.valueless_by_exception())
@@ -1537,6 +1563,11 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs,
 }
 
 template <class... _Types>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Types& __t) {
+    { __t >= __t } -> __core_convertible_to<bool>
+  } && ...)
+#    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
   using __variant_detail::__visitation::__variant;
   if (__rhs.valueless_by_exception())
diff --git a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
index c1a5b8e474a74..b8b2a41c888d1 100644
--- a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
@@ -39,8 +39,51 @@
 #include <utility>
 #include <variant>
 
+#include "test_comparisons.h"
 #include "test_macros.h"
 
+#if TEST_STD_VER >= 26
+
+// Test SFINAE.
+
+// ==
+static_assert(HasOperatorEqual<std::variant<int>>);
+static_assert(HasOperatorEqual<std::variant<EqualityComparable>>);
+
+static_assert(!HasOperatorEqual<std::variant<NonComparable>>);
+
+// >
+static_assert(HasOperatorGreaterThan<std::variant<int>>);
+static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable>>);
+
+static_assert(!HasOperatorGreaterThan<std::variant<NonComparable>>);
+
+// >=
+static_assert(HasOperatorGreaterThanEqual<std::variant<int>>);
+static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable>>);
+
+static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable>>);
+
+// <
+static_assert(HasOperatorLessThan<std::variant<int>>);
+static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable>>);
+
+static_assert(!HasOperatorLessThan<std::variant<NonComparable>>);
+
+// <=
+static_assert(HasOperatorLessThanEqual<std::variant<int>>);
+static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable>>);
+
+static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable>>);
+
+// !=
+static_assert(HasOperatorNotEqual<std::variant<int>>);
+static_assert(HasOperatorNotEqual<std::variant<EqualityComparable>>);
+
+static_assert(!HasOperatorNotEqual<std::variant<NonComparable>>);
+
+#endif
+
 #ifndef TEST_HAS_NO_EXCEPTIONS
 struct MakeEmptyT {
   MakeEmptyT() = default;
diff --git a/libcxx/test/support/test_comparisons.h b/libcxx/test/support/test_comparisons.h
index db6977a96a2fe..e37ab44828c70 100644
--- a/libcxx/test/support/test_comparisons.h
+++ b/libcxx/test/support/test_comparisons.h
@@ -268,6 +268,70 @@ struct PartialOrder {
   }
 };
 
-#endif
+template <typename T1, typename T2 = T1>
+concept HasOperatorEqual = requires(T1 t1, T2 t2) { t1 == t2; };
+
+template <typename T1, typename T2 = T1>
+concept HasOperatorGreaterThan = requires(T1 t1, T2 t2) { t1 > t2; };
+
+template <typename T1, typename T2 = T1>
+concept HasOperatorGreaterThanEqual = requires(T1 t1, T2 t2) { t1 >= t2; };
+template <typename T1, typename T2 = T1>
+concept HasOperatorLessThan = requires(T1 t1, T2 t2) { t1 < t2; };
+
+template <typename T1, typename T2 = T1>
+concept HasOperatorLessThanEqual = requires(T1 t1, T2 t2) { t1 <= t2; };
+
+template <typename T1, typename T2 = T1>
+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} {};
+
+  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
 
 #endif // TEST_COMPARISONS_H

>From ab710f4b2c1850b81003531e8e7f8cd2396feb36 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 May 2025 10:58:13 +0300
Subject: [PATCH 2/5] Implement tuple

---
 libcxx/include/tuple                          | 24 +++++++++
 libcxx/include/variant                        | 12 ++---
 .../tuple/tuple.tuple/tuple.rel/eq.pass.cpp   | 50 +++++++++++++++++--
 .../size_incompatible_comparison.verify.cpp   |  6 +++
 4 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 8dd62ae624f5e..8327c337b7f47 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -229,6 +229,7 @@ template <class... Types>
 #  include <__tuple/sfinae_helpers.h>
 #  include <__tuple/tuple_element.h>
 #  include <__tuple/tuple_indices.h>
+// #  include <__tuple/tuple_like.h>
 #  include <__tuple/tuple_like_ext.h>
 #  include <__tuple/tuple_size.h>
 #  include <__tuple/tuple_types.h>
@@ -1161,12 +1162,35 @@ struct __tuple_equal<0> {
 };
 
 template <class... _Tp, class... _Up>
+#    if _LIBCPP_STD_VER >= 26
+  requires(requires(const _Tp& __t, const _Up& __u) {
+            { __t == __u } -> __boolean_testable;
+          } && ...) && (sizeof...(_Tp) == sizeof...(_Up))
+#    endif
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
 operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
+#    if _LIBCPP_STD_VER < 26
   static_assert(sizeof...(_Tp) == sizeof...(_Up), "Can't compare tuples of different sizes");
+#    endif
   return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
 }
 
+// #    if _LIBCPP_STD_VER >= 23
+// template <class... _Tp, __tuple_like _UTuple>
+// #      if _LIBCPP_STD_VER >= 26
+//   requires((requires(const _Tp& __t, const _UTuple& __u) {
+//              { __t == __u } -> __boolean_testable;
+//            } && ...) && (sizeof...(_Tp) == tuple_size_v<_UTuple>))
+// #      endif
+// _LIBCPP_HIDE_FROM_ABI constexpr bool
+// operator==(const tuple<_Tp...>& __t, const _UTuple& __u) {
+// #      if _LIBCPP_STD_VER < 26
+//   static_assert(sizeof...(_Tp) == tuple_size_v<_UTuple>, "Can't compare a tuple and a tuple-like of different sizes");
+// #      endif
+//   return __tuple_equal<sizeof...(_Tp)>()(__t, __u);
+// }
+// #    endif
+
 #    if _LIBCPP_STD_VER >= 20
 
 // operator<=>
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 8dc3e9fb0f93b..f33058b708528 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1456,7 +1456,7 @@ struct __convert_to_bool {
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t == __t } -> __core_convertible_to<bool>
+    { __t == __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
@@ -1493,7 +1493,7 @@ operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t != __t } -> __core_convertible_to<bool>
+    { __t != __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
@@ -1508,7 +1508,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const variant<_Types...>& __lhs,
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t < __t } -> __core_convertible_to<bool>
+    { __t < __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
@@ -1527,7 +1527,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const variant<_Types...>& __lhs,
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t > __t } -> __core_convertible_to<bool>
+    { __t > __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
@@ -1546,7 +1546,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const variant<_Types...>& __lhs,
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t <= __t } -> __core_convertible_to<bool>
+    { __t <= __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
@@ -1565,7 +1565,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const variant<_Types...>& __lhs,
 template <class... _Types>
 #    if _LIBCPP_STD_VER >= 26
   requires(requires(const _Types& __t) {
-    { __t >= __t } -> __core_convertible_to<bool>
+    { __t >= __t } -> __core_convertible_to<bool>;
   } && ...)
 #    endif
 _LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
index a8de656313d45..d18bd1f29783f 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
@@ -11,19 +11,61 @@
 // template <class... Types> class tuple;
 
 // template<class... TTypes, class... UTypes>
-//   bool
-//   operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
+// constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); // constexpr since C++14
+
+// constexpr bool operator==(const tuple<TTypes...>&, const UTuple&);
+// template<class... TTypes, class... UTypes>                                   // Since C++23
 
 // UNSUPPORTED: c++03
 
-#include <tuple>
-#include <string>
+#include <array>
 #include <cassert>
+#include <tuple>
 
+#include "test_comparisons.h"
 #include "test_macros.h"
 
+#if TEST_STD_VER >= 26
+
+// Test SFINAE.
+
+// ==(const tuple<>&, const tuple<>&);
+
+static_assert(std::equality_comparable<std::tuple<EqualityComparable>>);
+static_assert(std::equality_comparable<std::tuple<EqualityComparable, EqualityComparable>>);
+
+static_assert(!std::equality_comparable<std::tuple<NonComparable>>);
+static_assert(!std::equality_comparable<std::tuple<EqualityComparable, NonComparable>>);
+static_assert(!std::equality_comparable<std::tuple<NonComparable, EqualityComparable>>);
+static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable>, std::tuple<NonComparable>>);
+static_assert(!std::equality_comparable_with<std::tuple<NonComparable>, std::tuple<EqualityComparable>>);
+// Size mismatch.
+static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable>, std::tuple<EqualityComparable, EqualityComparable>>);
+static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::tuple<EqualityComparable>>);
+
+// ==(const tuple<>&, const tuple-like&);
+
+// static_assert(std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::pair<EqualityComparable, EqualityComparable>>);
+// static_assert(std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::array<EqualityComparable, 2>>);
+
+// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, NonComparable>, std::pair<EqualityComparable, NonComparable>>);
+// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, NonComparable>, std::array<EqualityComparable, 2>>);
+// // Size mismatch.
+// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable>, std::pair<EqualityComparable, EqualityComparable>>);
+// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::array<EqualityComparable, 94>>);
+
+#endif
+
 int main(int, char**)
 {
+    // {
+    //     using T1 = std::tuple<int>;
+    //     using T2 = std::array<int, 1>;
+    //     const T1 t1(1);
+    //     const T2 t2{1};
+    //     assert(t1 == t2);
+    //     assert(!(t1 != t2));
+    // }
     {
         typedef std::tuple<> T1;
         typedef std::tuple<> T2;
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/size_incompatible_comparison.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/size_incompatible_comparison.verify.cpp
index 851f6fcd1fbac..a5dbb6b313e6a 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/size_incompatible_comparison.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/size_incompatible_comparison.verify.cpp
@@ -21,9 +21,15 @@
 
 #include <tuple>
 
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 26
+// expected-no-diagnostics
+#else
 void f(std::tuple<int> t1, std::tuple<int, long> t2) {
   // We test only the core comparison operators and trust that the others
   // fall back on the same implementations prior to C++20.
   static_cast<void>(t1 == t2); // expected-error@*:* {{}}
   static_cast<void>(t1 < t2); // expected-error@*:* {{}}
 }
+#endif

>From dd32d6c515281346347b6d9a4515671bebccc596 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 May 2025 11:00:25 +0300
Subject: [PATCH 3/5] Cleanup

---
 libcxx/include/tuple                          | 17 ------------
 .../tuple/tuple.tuple/tuple.rel/eq.pass.cpp   | 27 ++-----------------
 2 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 8327c337b7f47..35ea37a5ea5ed 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -229,7 +229,6 @@ template <class... Types>
 #  include <__tuple/sfinae_helpers.h>
 #  include <__tuple/tuple_element.h>
 #  include <__tuple/tuple_indices.h>
-// #  include <__tuple/tuple_like.h>
 #  include <__tuple/tuple_like_ext.h>
 #  include <__tuple/tuple_size.h>
 #  include <__tuple/tuple_types.h>
@@ -1175,22 +1174,6 @@ operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) {
   return __tuple_equal<sizeof...(_Tp)>()(__x, __y);
 }
 
-// #    if _LIBCPP_STD_VER >= 23
-// template <class... _Tp, __tuple_like _UTuple>
-// #      if _LIBCPP_STD_VER >= 26
-//   requires((requires(const _Tp& __t, const _UTuple& __u) {
-//              { __t == __u } -> __boolean_testable;
-//            } && ...) && (sizeof...(_Tp) == tuple_size_v<_UTuple>))
-// #      endif
-// _LIBCPP_HIDE_FROM_ABI constexpr bool
-// operator==(const tuple<_Tp...>& __t, const _UTuple& __u) {
-// #      if _LIBCPP_STD_VER < 26
-//   static_assert(sizeof...(_Tp) == tuple_size_v<_UTuple>, "Can't compare a tuple and a tuple-like of different sizes");
-// #      endif
-//   return __tuple_equal<sizeof...(_Tp)>()(__t, __u);
-// }
-// #    endif
-
 #    if _LIBCPP_STD_VER >= 20
 
 // operator<=>
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
index d18bd1f29783f..baca362f7783b 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp
@@ -11,10 +11,8 @@
 // template <class... Types> class tuple;
 
 // template<class... TTypes, class... UTypes>
-// constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); // constexpr since C++14
-
-// constexpr bool operator==(const tuple<TTypes...>&, const UTuple&);
-// template<class... TTypes, class... UTypes>                                   // Since C++23
+//   bool
+//   operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
 
 // UNSUPPORTED: c++03
 
@@ -29,8 +27,6 @@
 
 // Test SFINAE.
 
-// ==(const tuple<>&, const tuple<>&);
-
 static_assert(std::equality_comparable<std::tuple<EqualityComparable>>);
 static_assert(std::equality_comparable<std::tuple<EqualityComparable, EqualityComparable>>);
 
@@ -43,29 +39,10 @@ static_assert(!std::equality_comparable_with<std::tuple<NonComparable>, std::tup
 static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable>, std::tuple<EqualityComparable, EqualityComparable>>);
 static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::tuple<EqualityComparable>>);
 
-// ==(const tuple<>&, const tuple-like&);
-
-// static_assert(std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::pair<EqualityComparable, EqualityComparable>>);
-// static_assert(std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::array<EqualityComparable, 2>>);
-
-// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, NonComparable>, std::pair<EqualityComparable, NonComparable>>);
-// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, NonComparable>, std::array<EqualityComparable, 2>>);
-// // Size mismatch.
-// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable>, std::pair<EqualityComparable, EqualityComparable>>);
-// static_assert(!std::equality_comparable_with<std::tuple<EqualityComparable, EqualityComparable>, std::array<EqualityComparable, 94>>);
-
 #endif
 
 int main(int, char**)
 {
-    // {
-    //     using T1 = std::tuple<int>;
-    //     using T2 = std::array<int, 1>;
-    //     const T1 t1(1);
-    //     const T2 t2{1};
-    //     assert(t1 == t2);
-    //     assert(!(t1 != t2));
-    // }
     {
         typedef std::tuple<> T1;
         typedef std::tuple<> T2;

>From 23ebfd7e95f3fc97df572da0583786779cf48a54 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 May 2025 11:15:40 +0300
Subject: [PATCH 4/5] `variant` more tests

---
 .../variant/variant.relops/relops.pass.cpp     | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
index b8b2a41c888d1..2c00703662687 100644
--- a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
@@ -47,40 +47,46 @@
 // Test SFINAE.
 
 // ==
-static_assert(HasOperatorEqual<std::variant<int>>);
 static_assert(HasOperatorEqual<std::variant<EqualityComparable>>);
+static_assert(HasOperatorEqual<std::variant<EqualityComparable, int, long>>);
 
 static_assert(!HasOperatorEqual<std::variant<NonComparable>>);
+static_assert(!HasOperatorEqual<std::variant<NonComparable, EqualityComparable>>);
 
 // >
-static_assert(HasOperatorGreaterThan<std::variant<int>>);
 static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable>>);
+static_assert(HasOperatorGreaterThan<std::variant<ThreeWayComparable, int, long>>);
 
 static_assert(!HasOperatorGreaterThan<std::variant<NonComparable>>);
+static_assert(!HasOperatorGreaterThan<std::variant<NonComparable, ThreeWayComparable>>);
 
 // >=
-static_assert(HasOperatorGreaterThanEqual<std::variant<int>>);
 static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable>>);
+static_assert(HasOperatorGreaterThanEqual<std::variant<ThreeWayComparable, int, long>>);
 
 static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable>>);
+static_assert(!HasOperatorGreaterThanEqual<std::variant<NonComparable, ThreeWayComparable>>);
 
 // <
-static_assert(HasOperatorLessThan<std::variant<int>>);
 static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable>>);
+static_assert(HasOperatorLessThan<std::variant<ThreeWayComparable, int, long>>);
 
 static_assert(!HasOperatorLessThan<std::variant<NonComparable>>);
+static_assert(!HasOperatorLessThan<std::variant<NonComparable, ThreeWayComparable>>);
 
 // <=
-static_assert(HasOperatorLessThanEqual<std::variant<int>>);
 static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable>>);
+static_assert(HasOperatorLessThanEqual<std::variant<ThreeWayComparable, int, long>>);
 
 static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable>>);
+static_assert(!HasOperatorLessThanEqual<std::variant<NonComparable, ThreeWayComparable>>);
 
 // !=
-static_assert(HasOperatorNotEqual<std::variant<int>>);
 static_assert(HasOperatorNotEqual<std::variant<EqualityComparable>>);
+static_assert(HasOperatorNotEqual<std::variant<EqualityComparable, int, long>>);
 
 static_assert(!HasOperatorNotEqual<std::variant<NonComparable>>);
+static_assert(!HasOperatorNotEqual<std::variant<NonComparable, EqualityComparable>>);
 
 #endif
 

>From f862580a83cee9b7a73eb3ab804d057322fcf484 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 5 Jun 2025 06:48:47 +0300
Subject: [PATCH 5/5] Added missing include

---
 libcxx/include/tuple | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 35ea37a5ea5ed..15c9a1d743636 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -213,6 +213,7 @@ template <class... Types>
 #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
 #  include <__cxx03/__config>
 #else
+#  include <__concepts/boolean_testable.h>
 #  include <__compare/common_comparison_category.h>
 #  include <__compare/ordering.h>
 #  include <__compare/synth_three_way.h>



More information about the libcxx-commits mailing list