I'm looking for a way to implement the three-way comparison operator and the operator== for the following class:
class Foo
{
public:
auto operator<=>( const Foo& rhs ) const noexcept = default;
private:
std::uint32_t m_Y;
std::uint32_t m_X;
char m_C;
std::vector<char> m_Vec;
};
But the default
implementation is not what I intended. Therefore I need to write my own implementation.
What I want is:
==
and !=
) to be based on comparing the members m_Y
, m_X
, and m_C
of two operands (of type Foo
). All of those three members must be equal to satisfy the equality. The equality of the content of m_Vec
is not important (since it's not efficient to compare all those elements lexicographically).<
and >
) to be based on comparing the expression m_Y
* m_X
.<=
and >=
) to be based on comparing the expression m_Y
* m_X
and if both operands are equal in that regard, then all three members of both operands should be equal to satisfy the <=
or >=
(just like in ==
).Also with all this said, which comparison category type suits this scenario better, std::strong_ordering
or std::weak_ordering
?
How should I implement such logic? It seems simple and I read a whole recipe in a C++20 book on this topic and I still can't figure it out.
I believe this is a partial order, which is an order where elements may be incomparable (none of <
, >
, or ==
hold between them). You should verify the necessary laws hold (a <= b
iff a < b || a == b
, a <= a
for all a
, a == b
if a <= b && b <= a
for all a
, b
, and a <= c
if a <= b && b <= c
for all a
, b
, c
). If that is the case, use std::partial_ordering
.
std::partial_ordering operator<=>(Foo const &other) const noexcept {
// compare your * expression first
std::partial_ordering ret = (this->m_Y * this->m_X) <=> (other.m_Y * other.m_X);
if(ret != 0) return ret;
// if that's not informative, compare the fields
return std::tie(this->m_Y, this->m_X, this->m_C) == std::tie(other.m_Y, other.m_X, other.m_C)
? std::partial_ordering::equivalent : std::partial_ordering::unordered;
}