三路比较取代了除 == 之外的所有其他比较运算符?

Cha*_*eon 2 c++ spaceship-operator c++20

在 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;
}
Run Code Online (Sandbox Code Playgroud)

我在这里缺少什么?

Bar*_*rry 5

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

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

  • 相等运算符 ( ==, !=)
  • 排序运算符 ( <=>, <, >, <=, >=)

在每个类别中,我列出的第一个(==<=>)是主要的比较运算符。如果您想选择加入该类别,它是您需要定义的唯一运算符。如果您想要平等,请提供==. 如果您想订购,请提供<=>(以及==)。其他比较运算符是辅助比较运算符 - 使用辅助比较的表达式在 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; }
Run Code Online (Sandbox Code Playgroud)

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

有关更多信息,请参阅C++20 中的比较


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

auto operator<=>(const Iterator &a) const = default;
Run Code Online (Sandbox Code Playgroud)

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

bool operator==(const Iterator &a) const = default;
auto operator<=>(const Iterator &a) const = default;
Run Code Online (Sandbox Code Playgroud)

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