[libcxx-commits] [libcxx] [libc++] Fix std::variant comparators not working on recursive instantiations (PR #182238)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Mar 7 01:13:25 PST 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/182238
>From 234cb39bc18b824a7adec8657d700e74171e7654 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 19 Feb 2026 10:35:48 +0100
Subject: [PATCH 1/2] [libc++] Fix std::variant comparators not working on
recursive instantiations
---
libcxx/include/variant | 3 +-
.../variant/variant.relops/relops.pass.cpp | 65 +++++++++++++++++++
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 56c5efe92b642..9b2c4ee23ddcf 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -614,7 +614,8 @@ private:
template <class _Visitor>
struct __value_visitor {
template <class... _Alts>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Alts&&... __alts) const {
+ _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Alts&&... __alts) const
+ -> invoke_result_t<_Visitor&&, decltype((std::forward<_Alts>(__alts).__value))...> {
__std_visit_exhaustive_visitor_check< _Visitor, decltype((std::forward<_Alts>(__alts).__value))...>();
return std::__invoke(std::forward<_Visitor>(__visitor), std::forward<_Alts>(__alts).__value...);
}
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 2c00703662687..7a55aab52ebc5 100644
--- a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
@@ -317,6 +317,71 @@ void test_relational() {
#endif
}
+struct A1 {
+ bool operator==(const A1&) const { return true; }
+ bool operator!=(const A1&) const { return true; }
+ bool operator<(const A1&) const { return true; }
+ bool operator>(const A1&) const { return true; }
+ bool operator<=(const A1&) const { return true; }
+ bool operator>=(const A1&) const { return true; }
+};
+struct A2 {
+ bool operator==(const A2&) const { return true; }
+ bool operator!=(const A2&) const { return true; }
+ bool operator<(const A2&) const { return true; }
+ bool operator>(const A2&) const { return true; }
+ bool operator<=(const A2&) const { return true; }
+ bool operator>=(const A2&) const { return true; }
+};
+
+struct Array;
+
+using Var1 = std::variant<A1, Array>;
+using Var2 = std::variant<A2, Array>;
+
+struct Array {
+ Var1* ptr;
+
+ template <class Other>
+ friend constexpr bool operator==(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr == *rhs.ptr;
+ }
+
+ template <class Other>
+ friend constexpr bool operator!=(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr != *rhs.ptr;
+ }
+
+ template <class Other>
+ friend constexpr bool operator<(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr < *rhs.ptr;
+ }
+
+ template <class Other>
+ friend constexpr bool operator>(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr > *rhs.ptr;
+ }
+
+ template <class Other>
+ friend constexpr bool operator<=(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr <= *rhs.ptr;
+ }
+
+ template <class Other>
+ friend constexpr bool operator>=(const Array& lhs, const Other& rhs) {
+ return *lhs.ptr >= *rhs.ptr;
+ }
+};
+
+void test_recursive() {
+ (void)(Var2{} == Var2{});
+ (void)(Var2{} != Var2{});
+ (void)(Var2{} < Var2{});
+ (void)(Var2{} > Var2{});
+ (void)(Var2{} <= Var2{});
+ (void)(Var2{} >= Var2{});
+}
+
int main(int, char**) {
test_equality();
test_relational();
>From 13155f4213f1b46758d31de197a2651838517e1f Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sat, 7 Mar 2026 10:13:17 +0100
Subject: [PATCH 2/2] Update
libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
---
libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp | 1 +
1 file changed, 1 insertion(+)
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 7a55aab52ebc5..54eb1e7321ff9 100644
--- a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
@@ -373,6 +373,7 @@ struct Array {
}
};
+// See https://llvm.org/PR182232
void test_recursive() {
(void)(Var2{} == Var2{});
(void)(Var2{} != Var2{});
More information about the libcxx-commits
mailing list