When overloading operator==(), I currently do
bool operator==(const X& lhs, const X& rhs)
{
return &lhs == &rhs || /* member comparisons
Self comparison is usually rare, unless you are an immutable internal pImpl that is usually only compared via ==
in an unordered_
container after a std::hash
collision of your regular wrapper, or something similar.
Optimizing for rare cases is often a bad idea. It adds complexity to the code, and increases testing overhead.
An exception can exist if the comparison is expensive or boundlessly expensive, so that the cost of a failed pointer comparison at the start is trivial. Another exception is where self comparison is unusually expensive, and almost-self (which would be almost as expensive) is exceedingly rare, while self comparison sometimes happens.
The short answer is, keep your code simple, worry about large-order blowups, don't needlessly pessimize, and optimize after actually noticing a performance problem (even if it is just "wow, that was slow", or Monte Carlo profiling).