[libc++] Fix missing requires clause on variant operator<=>

`std::variant::operator<=>` is missing a requires clause ensuring that
`operator<=>` only exists when all of the types in the variant are
`three_way_comparable`.

Add the missing requires clause and adjust the existing test which was
incorrect.

Fixes https://github.com/llvm/llvm-project/issues/58192.

Differential Revision: https://reviews.llvm.org/D136050
This commit is contained in:
Joe Loser 2022-10-16 18:47:26 -06:00
parent 021e6e05d3
commit dd9afdbb2a
2 changed files with 6 additions and 10 deletions

View File

@ -165,7 +165,7 @@ namespace std {
template <class... Types>
constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&);
template <class... Types>
template <class... Types> requires (three_way_comparable<Types> && ...)
constexpr common_comparison_category_t<compare_three_way_result_t<Types>...>
operator<=>(const variant<Types...>&, const variant<Types...>&); // since C++20
@ -1638,7 +1638,7 @@ constexpr bool operator==(const variant<_Types...>& __lhs,
# if _LIBCPP_STD_VER > 17
template <class... _Types>
template <class... _Types> requires (three_way_comparable<_Types> && ...)
_LIBCPP_HIDE_FROM_ABI constexpr common_comparison_category_t<compare_three_way_result_t<_Types>...>
operator<=>(const variant<_Types...>& __lhs, const variant<_Types...>& __rhs) {
using __variant_detail::__visitation::__variant;

View File

@ -12,7 +12,7 @@
// template <class... Types> class variant;
// template<class... Types>
// template <class... Types> requires (three_way_comparable<Types> && ...)
// constexpr std::common_comparison_category_t<
// std::compare_three_way_result_t<Types>...>
// operator<=>(const variant<Types...>& t, const variant<Types...>& u);
@ -170,15 +170,11 @@ static_assert(!has_three_way_op<std::variant<int, HasSimpleOrdering>>);
static_assert(!three_way_comparable<HasSimpleOrdering>);
static_assert(!three_way_comparable<std::variant<int, HasSimpleOrdering>>);
static_assert( has_three_way_op<HasOnlySpaceship>);
static_assert( has_three_way_op<std::variant<int, HasOnlySpaceship>>);
static_assert(has_three_way_op<HasOnlySpaceship>);
static_assert(!has_three_way_op<std::variant<int, HasOnlySpaceship>>);
// variants containing types with unavailable operator== still exist but will
// generate a compilation error if their operator== is invoked, so the variant
// type here participates when asked for operator== and operator<=> even though
// it would actually fail.
static_assert(!three_way_comparable<HasOnlySpaceship>);
static_assert( three_way_comparable<std::variant<int, HasOnlySpaceship>>);
static_assert(!three_way_comparable<std::variant<int, HasOnlySpaceship>>);
static_assert( has_three_way_op<HasFullOrdering>);
static_assert( has_three_way_op<std::variant<int, HasFullOrdering>>);