Issue 58192
Summary variant's operator<=> is missing a requires-clause
Labels libc++, c++20
Assignees
Reporter CaseyCarter
    [variant.syn] declares variant's spaceship operator as:
```c++
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...>&);
```
libc++ implements this operator, but without the _requires-clause_ `requires (three_way_comparable<Types> && ...)`:

https://github.com/llvm/llvm-project/blob/e2378d343828df73dd640fd1d1f5e02feb4ac0ef/libcxx/include/variant#L1641-L1643

The absence of the _requires-clause_ causes the operator to sometimes be present under conditions in which the standard specifies it should not be, such as a variant with an alternative type that implements `<=>` but not `==` (https://godbolt.org/z/f7Mh3vMxM):
```c++
struct X {
    bool operator==(const X&) const = delete;
    auto operator<=>(const X&) const = default;
};

template <class T>
concept can_spaceship = requires(const T& x, const T& y) {
    x <=> y;
};

static_assert(!can_spaceship<std::variant<X>>);
```
The `static_assert` in this example program fails with libc++ but should pass. If fact, libc++ has a test case for this exact behavior:

https://github.com/llvm/llvm-project/blob/e2378d343828df73dd640fd1d1f5e02feb4ac0ef/libcxx/test/std/utilities/variant/variant.relops/three_way.pass.cpp#L174

which will also need to be fixed.

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to