In C++20 we got a new three-way comparison operator <=> , which typically returns std::strong_ordering or std::partial_ordering types. And if class A has operator <=>, then the comparison of its objects a1 < a2 is interpreted as (a1 <=> a2) < 0.
But can the user overload comparison operators, taking the first argument of type std::strong_ordering and the second argument accepting 0 literal? For example:
#include <compare>
#include <iostream>
struct A {
std::strong_ordering operator <=>(const A &) const = default;
};
void operator < (std::strong_ordering, std::nullptr_t) {
std::cout << "overloaded< ";
}
int main() {
A{} < A{}; // #1
(A{} <=> A{}) < 0; //#2
}
Here both GCC and Clang call overloaded operator <, even without any warning about the presence of another operator in the standard library. Is it ok? Demo: https://gcc.godbolt.org/z/zEEP45Ezj
The behavior of MSVC is more interesting. In #1 it prints a weird error:
error C2088: '<': illegal for struct
In #2:
error C2593: 'operator <' is ambiguous
<source>(8): note: could be 'void operator <(std::strong_ordering,std::nullptr_t)'
C:/data/msvc/14.30.30423-Pre/include\compare(189): note: or 'bool std::operator <(const std::strong_ordering,std::_Literal_zero) noexcept' [found using argument-dependent lookup]
<source>(14): note: while trying to match the argument list '(std::strong_ordering, int)'
Personally I would prefer this behavior, but what is the right one here?