There are some new rules about rewritten comparison operators in C++20, and I'm trying to understand how they work. I've run into the following program:
struct B {};
struct A
{
bool operator==(B const&); // #1
};
bool operator==(B const&, A const&); // #2
int main()
{
B{} == A{}; // C++17: calls #2
// C++20: calls #1
}
which actually breaks existing code. I'm a little surprised by this; #2 actually still looks better to me :p
So how do these new rules change the meaning of existing code?
That particular aspect is a simple form of rewriting, reversing the operands. The primary operators
==and<=>can be reversed, the secondaries!=,<,>,<=, and>=, can be rewritten in terms of the primaries.The reversing aspect can be illustrated with a relatively simple example.
If you don't have a specific
B::operator==(A)to handleb == a, you can use the reverse to do it instead:A::operator==(B). This makes sense because equality is a bi-directional relationship:(a == b) => (b == a).Rewriting for secondary operators, on the other hand, involves using different operators. Consider
a > b. If you cannot locate a function to do that directly, such asA::operator>(B), the language will go looking for things likeA::operator<=>(B)then simply calculating the result from that.That's a simplistic view of the process but it's one that most of my students seem to understand. If you want more details, it's covered in the
[over.match.oper]section of C++20, part of overload resolution (@is a placeholder for the operator):Hence gone are the days of having to provide a real
operator==andoperator<, then boiler-plating:Don't complain if I've gotten one or more of those wrong, that just illustrates my point on how much better C++20 is, since you now only have to provide a minimal set (most likely just
operator<=>plus whatever else you want for efficiency) and let the compiler look after it :-)The question as to why one is being selected over the other can be discerned with this code:
The output of that indicates that it's the
const-ness ofadeciding which is the better candidate.As an aside, you may want to have a look at this article, which offers a more in-depth look.