三向比较取代所有其他比较运算符,除了 ==?

Three way comparison replaces all others comparison operators except ==?

在 g++ 10 中,我尝试使用三向比较,仅用于实验。

我读到其他运算符不再需要(== 除外)。

但即使我可以使用运算符(它是在编译器上实现的),它也不会取代(或暗示)!=。

所以,下面的代码是行不通的。

#include<iostream>

using namespace std;

struct A
{
    struct Iterator
    {
        size_t index;
        size_t operator*() { return index + 1000; }
        //bool operator!=(const Iterator &a) const { return index != a.index; }
        auto operator<=>(const Iterator &a) const { return index <=> a.index; }
        Iterator &operator++() { ++index; return *this; }
    };
    Iterator begin() { return Iterator{0}; }
    Iterator end() { return Iterator{5}; }
};


int main()
{
    A a;
    auto result = a.begin() <=> a.end();
    for (auto b : a)
        cout << b << "\n";
    cout << (a.begin() != a.end()) << "\n";

    return 0;
}

我在这里错过了什么?

来自cppreference

In brief, a class that defines operator<=> automatically gets compiler-generated operators <, <=, >, and >=. A class can define operator<=> as defaulted, in which case the compiler will also generate the code for that operator."

不会生成 != 和 == 的代码,因此您需要执行比较。

operator == 对于定义为默认的每个运算符 operator <=> 隐式声明为默认:

#include<iostream>

using namespace std;

struct A
{
    struct Iterator
    {
        size_t index;
        size_t operator*() { return index + 1000; }
        //bool operator!=(const Iterator &a) const { return index != a.index; }

        auto operator<=>(const Iterator &) const = default;
        // bool operator == (const Iterator&) const; implicitly declared

        Iterator &operator++() { ++index; return *this; }
    };
    Iterator begin() { return Iterator{0}; }
    Iterator end() { return Iterator{5}; }
};


int main()
{
    A a;
    auto result = a.begin() <=> a.end();
    for (auto b : a)
        cout << b << "\n";
    cout << (a.begin() != a.end()) << "\n";

    return 0;
}

I read that other operators do not needed anymore (except ==).

对了,除了==是关键位。比较运算符分为两类:

  • 等式运算符(==!=
  • 排序运算符(<=><><=>=

在每个类别中,我列出的第一个(==<=>)是 primary 比较运算符。如果您想选择加入该类别,它是您唯一需要定义的运算符。如果您想要平等,请提供 ==。如果您想订购,请提供 <=>(以及 ==)。其他比较运算符是 secondary 比较运算符 - 使用次要比较的表达式在 C++20 中重写为使用主要比较运算符。

这些类别完全不同 - 没有交叉。 x != y 表达式可以调用 operator==(x, y) 甚至 operator==(y, x) 但它永远不会调用任何类型的 operator<=>

您的代码需要进行相等比较,但没有定义相等运算符,因此格式错误。要使其正常工作,您需要添加:

bool operator==(const Iterator &a) const { return index == a.index; }
auto operator<=>(const Iterator &a) const { return index <=> a.index; }

注意 ==,而不是 !=。你不应该在 C++20 中声明辅助比较运算符,除非你对它们有非常具体的需要(而这不是这样的需要)。

有关更多信息,请参阅 Comparisons in C++20


此规则的唯一例外是,为了方便起见,如果您 default operator<=> 那么您 得到一个声明的,默认的operator==。就好像你自己都违约了一样。在此示例中,由于您的比较只是默认的成员比较,您可以这样写:

auto operator<=>(const Iterator &a) const = default;

作为您的单个比较运算符声明,其行为就像您编写的那样:

bool operator==(const Iterator &a) const = default;
auto operator<=>(const Iterator &a) const = default;

这为您提供了程序所需的正确相等运算符。