I am learning about std::strong_ordering and std::weak_ordering in C++20. According to the docs, std::strong_ordering requires that equivalent values be indistinguishable, as opposed to std::weak_ordering.
When researching std::weak_ordering (especially in the context of the spaceship operator, <=>), I generally encounter examples similar to the one below, which represents a multiplication expression:
// Represents a multiplication expression, the result of which is (multiplicand * multiplier)
struct Multiplication {
int multiplicand;
int multiplier;
};
This struct appears like it should be weakly ordered as different pairs of multiplicands and multipliers can evaluate to the same result, meaning equivalent values can be distinguishable (Multiplication{3, 2}, Multiplication{6, 1}, and Multiplication{1, 6} all technically represent 6).
However, the trivial approach for comparing different Multiplication structs actually returns an std::strong_ordering because multiplication results are ints and hence strongly ordered.
struct Multiplication {
int multiplicand;
int multiplier;
// This returns std::strong_ordering by default
auto operator<=>(Multiplication rhs) const
{
return (multiplicand * multiplier) <=> (rhs.multiplicand * rhs.multiplier);
}
};
Is it then my responsibility to explicitly annotate the return type as std::weak_ordering in this case to make it semantically accurate?
This is incorrect. It requires "substitutability", which in the standard is defined as:
That's a very narrow definition, one that allows for
aandbto have differences in data so long as they are not "comparison-salient".That being said:
Yes. The compiler cannot know what is "substitutable" and what is not. This is a semantic property, and it is always up to the programmer to define it.
And yes, your
Multiplicationstruct is not substitutable.