From 70b20e5c8a5fa289f68b2359dbbb52f07120f412 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 11 Sep 2026 10:59:16 +0800 Subject: [PATCH 1/2] Use a simpler three-way comparator for `variant` --- stl/inc/variant | 15 +++++++++++++-- tests/libcxx/expected_results.txt | 3 --- tests/std/tests/P0088R3_variant/test.cpp | 9 --------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/stl/inc/variant b/stl/inc/variant index 8948643a39e..0e2f45d6105 100644 --- a/stl/inc/variant +++ b/stl/inc/variant @@ -1376,15 +1376,26 @@ _NODISCARD constexpr bool operator>=(const variant<_Types...>& _Left, const vari } #if _HAS_CXX20 +// This is equivalent to `compare_three_way`, +// except for no support for non-const comparison, simpler constraints, and explicit return type. +struct _Simpler_compare_three_way { + template + _NODISCARD static constexpr auto operator()(const _Ty1& _Left, const _Ty2& _Right) // + noexcept(noexcept(_Left <=> _Right)) // + /*-*/ -> decltype(_Left <=> _Right) { + /*------*/ return _Left <=> _Right; + } +}; + _EXPORT_STD template requires (three_way_comparable<_Types> && ...) _NODISCARD constexpr common_comparison_category_t...> operator<=>( const variant<_Types...>& _Left, const variant<_Types...>& _Right) noexcept(conjunction_v...>, - compare_three_way, const _Types&, const _Types&>...>) /* strengthened */ { + _Simpler_compare_three_way, const _Types&, const _Types&>...>) /* strengthened */ { // determine the three-way comparison of _Left's and _Right's index, if equal // return the three-way comparison of the contained values of _Left and _Right - using _Visitor = _Variant_relop_visitor2...>, _Types...>; const size_t _Left_offset = _Left.index() + 1; const size_t _Right_offset = _Right.index() + 1; diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 68e9d9f6fdd..a947cee74d3 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -1161,9 +1161,6 @@ std/algorithms/alg.sorting/alg.set.operations/set.symmetric.difference/ranges_se std/algorithms/alg.sorting/alg.set.operations/set.union/ranges_set_union.pass.cpp:0 SKIPPED std/algorithms/alg.sorting/alg.set.operations/set.union/ranges_set_union.pass.cpp:1 SKIPPED -# Not analyzed. Clang emits a -Wundefined-inline warning. -std/utilities/variant/variant.relops/three_way.pass.cpp:2 FAIL - # Not analyzed. # MSVC error C2719: '_Fun_': formal parameter with requested alignment of 128 won't be aligned # Clang error: unknown attribute 'no_unique_address' ignored [-Werror,-Wunknown-attributes] diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 8a5beedb993..89cdb0d8508 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -1474,20 +1474,11 @@ struct HasOnlySpaceship { constexpr std::weak_ordering operator<=>(const HasOnlySpaceship&) const; }; -#ifdef __clang__ // TRANSITION, not yet investigated -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wundefined-inline" -#endif // ^^^ workaround ^^^ - struct HasFullOrdering { constexpr bool operator==(const HasFullOrdering&) const; constexpr std::weak_ordering operator<=>(const HasFullOrdering&) const; }; -#ifdef __clang__ // TRANSITION, not yet investigated -#pragma clang diagnostic pop -#endif // ^^^ workaround ^^^ - // operator<=> must resolve the return types of all its union types' // operator<=>s to determine its own return type, so it is detectable by SFINAE static_assert(!has_three_way_op); From 4310c9b26a98f3db1fb8736c84ab4afe974e5819 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Fri, 11 Sep 2026 19:00:41 +0800 Subject: [PATCH 2/2] Mirror LLVM-222837 --- tests/std/tests/P0088R3_variant/test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/std/tests/P0088R3_variant/test.cpp b/tests/std/tests/P0088R3_variant/test.cpp index 89cdb0d8508..2466cd68169 100644 --- a/tests/std/tests/P0088R3_variant/test.cpp +++ b/tests/std/tests/P0088R3_variant/test.cpp @@ -1465,18 +1465,18 @@ concept has_three_way_op = requires (T& t, U& u) { t <=> u; }; using std::three_way_comparable; struct HasSimpleOrdering { - constexpr bool operator==(const HasSimpleOrdering&) const; - constexpr bool operator<(const HasSimpleOrdering&) const; + bool operator==(const HasSimpleOrdering&) const; + bool operator<(const HasSimpleOrdering&) const; }; struct HasOnlySpaceship { - constexpr bool operator==(const HasOnlySpaceship&) const = delete; - constexpr std::weak_ordering operator<=>(const HasOnlySpaceship&) const; + bool operator==(const HasOnlySpaceship&) const = delete; + std::weak_ordering operator<=>(const HasOnlySpaceship&) const; }; struct HasFullOrdering { - constexpr bool operator==(const HasFullOrdering&) const; - constexpr std::weak_ordering operator<=>(const HasFullOrdering&) const; + bool operator==(const HasFullOrdering&) const; + std::weak_ordering operator<=>(const HasFullOrdering&) const; }; // operator<=> must resolve the return types of all its union types'