如何为非 POD class 正确实施 operator<=>?

How to properly implement operator<=> for a non-POD class?

我正在寻找一种方法来实现 三向比较运算符 运算符== 以下 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;
};

但是 default 实现不是我想要的。因此我需要编写自己的实现。

我想要的是:

  1. 我希望 相等 比较(==!=)基于比较成员 m_Ym_X,以及两个操作数(Foo 类型)的 m_C。所有这三个成员都必须相等才能满足相等性。 m_Vec 的内容是否相等并不重要(因为按字典顺序比较所有这些元素效率不高)。
  2. 我希望 排序 比较(<>)基于比较表达式 m_Y * m_X.
  3. 我希望 排序 比较(<=>=)基于比较表达式 m_Y * m_X 如果两个操作数在这方面是相等的,那么两个操作数的所有三个成员都应该相等以满足 <=>=(就像在 ==).

综上所述,哪种比较类别类型更适合这种情况,std::strong_orderingstd::weak_ordering

我应该如何实现这样的逻辑?这看起来很简单,我在一本关于这个主题的 C++20 书中阅读了整个食谱,但我仍然无法弄明白。

我相信这是一个偏序,这是一个元素可能无法比较的顺序(<>== 中的 none 在它们之间).您应该验证必要的法律成立 (a <= b iff a < b || a == b, a <= a 对于所有 a, a == b 如果 a <= b && b <= a 对于所有 aba <= c(如果 a <= b && b <= c 用于所有 abc)。如果是这种情况,请使用 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;
}