-1

In comments on In C++ do you need to overload operator== in both directions? Story teller waxes enthusistic about the simplified oveloading provided in c++20 with the <=> operator.

That's why operator <=> generates so much excitement. Because it can cut down on a lot of boilerplate

So with one step (and function) we create overloads for less than greater than equal to and all their negations. Great for anything with sequence. Now I am a contrary fellow and my first thought is what about objects without sequence or a need for sequence where there is only the need for equality (or inequality) testing? for example lets say we are doing unit comparison so meter == second should obviously be false, but what about meter < second or even meter <=> second, as the are both nonsense, or should any order just be picked to complete the model like alphabetic. (which would give us false and -1)

9
  • I don't see the comment you are referring to. Nov 15, 2018 at 1:33
  • @RobertHarvey, He has several comments on the question and answers.
    – hildred
    Nov 15, 2018 at 1:45
  • 2
    "what about objects without sequence or a need for sequence where there is only the need for equality (or inequality) testing?" Why would meter even be testable against second? The question itself makes no sense; in what way could they be equal to one another? Nov 15, 2018 at 7:43
  • 3
    You are getting it wrong. Comparison of meters and seconds should not be false or true at all, it should not compile.
    – Teimpz
    Nov 15, 2018 at 9:57
  • 1
    @hildred: That makes less sense. How do you compare units? What is the relationship between the concept of a meter and the concept of a second? Nov 21, 2018 at 14:29

4 Answers 4

8

When a new feature is added to a language, you shouldn't start using it blindly. There will often still be cases where the old features are either better, or the only option.

The <=> operator is very useful for the common case. But if you're not in the common case, then there is no reason for you to use it.

1
5

Before C++20, if there wasn't a sensible ordering between a pair of types, you wouldn't implement a whole family of operators: two each of <, >, <=, >= for A @ B and B @ A.

After C++20, if there isn't a sensible ordering between a pair of types, you don't implement one more operator, <=>.

so meter == second should obviously be false

No, meter == second should be a type error

The excitement comes from the (rather common) case where there is a sensible ordering.

3

As pointed out in several answers and comments, the meters == seconds case is not relevant to the title question.

So, let's focus on the title question, which stands on its own:

Is simplifying overloading always a good thing?

It was commented elsewhere that one of the arguments is convenience.

Because it can cut down on a lot of boilerplate

However, I would say that convenience is second to correctness.

When a programmer is forced to overload each of the pre-C++20 ordered comparison operators, there is a possibility that either a typo or a thinko (a misthought) could lead to an inconsistent implementation.

As an example, early in my career I once implemented a strict weak ordering operator by calling std::greater_equal, thinking that it was the natural choice since it was the logical negation of std::less.

Here's an experiment. Try store a few instances of this object in any C++ ordered container. Alternatively, store them in a std::vector, and then call std::sort. Compile and run.

Infinite loop, exception, uncaught exception, or std::abort. Why?

(Remark) The latter cases are possible in debug mode. In release mode, anything could happen, with infinite loop being most likely. Truly undefined behavior other than infinite loop only happens if the container is tree-based due to tree node management failure.

The contract for std::sort or for the order maintenance algorithms in C++ containers depend on these comparison operators being consistent at all times. For example, a strict weak ordering must be strict at all times. Note A failure to do so not only causes unspecified behavior; they actually lead to worse things such as potential infinite loops. Because algorithm implementations take advantage of the assumption that user-defined comparison operators need to be consistent, that inconsistency isn't tolerated at all. Preventing the worse outcome from noncompliant implementation imposes a runtime cost on all software, which annoys experienced programmers because experienced programmers don't make this kind of mistakes.

(Note) Specifically, (A @ B) and (B @ A) cannot be both true, when @ is a strict weak ordering.

This is my experience many years ago. Things may have changed; new algorithm implementations might have better built-in defense against noncompliant / inconsistent comparison operator overloads. But why take the risk?

3

The operator is aimed squarely at classes that have a natural strict-weak ordering.

There is a way to label every object instance of the class with a natural number, such that the result of comparing any two object instances is the same as comparing the labels of those two objects.

Does your class have that property or not? If not, don't implement the operator.


Edit

As has been pointed out, the <=> operator(under Three-way Comparison) covers Partial Orderings as well.

I would still use caution and suggest following the Strict-weak ordering as far as possible, and being very clear when you ordering does not follow it, to provide the least amount of surprise to the class' users.

As always only provide operators when it is clear what they mean. To do this lean heavily on established conventions.

If your lucky enough to be operating in a new environment, be careful what you chose as they may become the de-facto standard.

3
  • Only for strict weak ordering? No, the target is much bigger. Nov 15, 2018 at 17:54
  • "natural strict-weak ordering" even one that doesn't imply equality as defined by ==?
    – curiousguy
    Nov 20, 2018 at 3:13
  • Again, in my edit I pointed out that my advice follows the principle of least surprise. The operators ==, !=, <, <=, >, >= are taught in programming in a single set, usually using integers or strings as the target for sorting. Many will skip the fact that text has many collations that complicate sorting and use their binary encoding instead. This does enforce the notion that these operators have Strict-Weak ordering - implying that !(a<b)&&!(a>b) is equivalent to a==b. So call-out the specific sorting and equivalence relation, but don't implement one if its not natural.
    – Kain0_0
    Nov 20, 2018 at 22:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.