You would not want the language to automatically rewrite a != b
as !(a == b)
when a == b
returns something other than a bool
. And there are a few reasons why you might make it do that.
You may have expression builder objects, where a == b
doesn’t and isn’t intended to perform any comparison, but simply builds some expression node representing a == b
.
You may have lazy evaluation, where a == b
doesn’t and isn’t intended to perform any comparison directly, but instead returns some kind of lazy<bool>
that can be converted to bool
implicitly or explicitly at some later time to actually perform the comparison. Possibly combined with the expression builder objects to allow complete expression optimisation before evaluation.
You may have some custom optional<T>
template class, where given optional variables t
and u
, you want to allow t == u
, but make it return optional<bool>
.
There’s probably more that I didn’t think of. And even though in these examples the operation a == b
and a != b
do both make sense, still a != b
isn’t the same thing as !(a == b)
, so separate definitions are needed.