Issue |
148556
|
Summary |
Missing suggestion in error message with defaulted three-way comparison when return type is auto
|
Labels |
new issue
|
Assignees |
|
Reporter |
jonathanpoelen
|
When defining a struct that provides at least `==` and `<` operators but not a three-way comparison operator, and using `auto operator<=>(T const&) = default;` in another struct, Clang emits an error indicating that the defaulted operator<=> is implicitly deleted.
```cpp
<source>:15:12: error: object of type 'Item' cannot be compared because its 'operator<=>' is implicitly deleted
15 | Item{} < Item{};
| ^
<source>:11:10: note: explicitly defaulted function was implicitly deleted here
11 | auto operator<=>(const Item &other) const = default;
| ^
<source>:9:7: note: defaulted 'operator<=>' is implicitly deleted because there is no viable three-way comparison function for member 'text'
9 | A text;
| ^
```
This message is unclear for users who have correctly implemented `==` and `<`. GCC, in comparison, provides a much more helpful message suggesting to change the return type from `auto` to a comparison category type to allow the comparison to use `operator<` and `operator==`:
```cpp
<source>:11:10: note: changing the return type from 'auto' to a comparison category type will allow the comparison to use 'operator<' and 'operator=='
11 | auto operator<=>(const Item &other) const = default;
| ^~~~~~~~
```
## Desired Behavior
- Suggest, as GCC does, that changing the return type from `auto` to a comparison category type (e.g., `std::strong_ordering` or `std::partial_ordering`) would allow `operator<=>` to fall back on `operator<` and `operator==`.
## Environment
- Clang version: 17, 18, 19, 20
## Code to reproduce
https://godbolt.org/z/6hzfPc7er
```cpp
#include <compare>
struct A {};
bool operator==(A const&, A const&);
bool operator<(A const&, A const&);
struct Item {
A text;
auto operator<=>(const Item &other) const = default;
};
int main() {
Item{} < Item{};
}
```
### Full Clang Output
```cpp
<source>:11:10: warning: explicitly defaulted three-way comparison operator is implicitly deleted [-Wdefaulted-function-deleted]
11 | auto operator<=>(const Item &other) const = default;
| ^
<source>:9:7: note: defaulted 'operator<=>' is implicitly deleted because there is no viable three-way comparison function for member 'text'
9 | A text;
| ^
<source>:11:49: note: replace 'default' with 'delete'
11 | auto operator<=>(const Item &other) const = default;
| ^~~~~~~
| delete
<source>:15:12: error: object of type 'Item' cannot be compared because its 'operator<=>' is implicitly deleted
15 | Item{} < Item{};
| ^
<source>:11:10: note: explicitly defaulted function was implicitly deleted here
11 | auto operator<=>(const Item &other) const = default;
| ^
<source>:9:7: note: defaulted 'operator<=>' is implicitly deleted because there is no viable three-way comparison function for member 'text'
9 | A text;
| ^
```
### Full Gcc Output
```cpp
<source>:15:19: error: use of deleted function 'constexpr auto Item::operator<=>(const Item&) const'
15 | Item{} < Item{};
| ^
<source>:11:10: note: 'constexpr auto Item::operator<=>(const Item&) const' is implicitly deleted because the default definition would be ill-formed:
11 | auto operator<=>(const Item &other) const = default;
| ^~~~~~~~
<source>:9:7: error: no match for 'operator<=>' (operand types are 'A' and 'A')
9 | A text;
| ^~~~
<source>:11:10: note: changing the return type from 'auto' to a comparison category type will allow the comparison to use 'operator<' and 'operator=='
11 | auto operator<=>(const Item &other) const = default;
| ^~~~~~~~
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs