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?
According to the docs,
std::strong_orderingrequires that equivalent values be indistinguishable, as opposed tostd::weak_ordering.
This is incorrect. It requires "substitutability", which in the standard is defined as:
the property that
f(a) == f(b)is true whenevera == bis true, wherefdenotes a function that reads only comparison-salient state that is accessible via the argument’s public const members.
That's a very narrow definition, one that allows for a and b to have differences in data so long as they are not "comparison-salient".
That being said:
Is it then my responsibility to explicitly annotate the return type as
std::weak_orderingin this case to make it semantically accurate?
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 Multiplication struct is not substitutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With