【问题标题】:Three way comparison replaces all others comparison operators except ==?三向比较取代了除 == 之外的所有其他比较运算符?
【发布时间】:2020-06-26 02:34:24
【问题描述】:

在 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;
}

我在这里错过了什么?

【问题讨论】:

  • 您知道吗,您总是在beginend 函数中返回一个新对象?
  • @NutCracker 是的。对于这么小的东西,这不是一笔交易。
  • @NutCracker 迭代器应该是轻量级的,按值返回是 begin()end() 通常的实现方式。
  • @Chameleon 我相信你也需要包含&lt;compare&gt;。否则,如果我理解规范,程序是不正确的。正确......也许不是......我被困在这里:eel.is/c++draft/expr.spaceship#9

标签: c++ c++20 spaceship-operator


【解决方案1】:

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

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

  • 等式运算符(==!=
  • 排序运算符(&lt;=&gt;&lt;&gt;&lt;=&gt;=

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

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

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

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


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

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

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

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

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

【讨论】:

    【解决方案2】:

    来自cppreference

    简而言之,定义 operator&lt;=&gt; 的类会自动获取编译器生成的运算符 > >>=。一个类可以将operator&lt;=&gt; 定义为默认值,在这种情况下,编译器也会为该运算符生成代码。”

    != 和 == 的代码未生成,因此您需要实现比较。

    【讨论】:

      【解决方案3】:

      operator == 被隐式声明为默认的每个运算符operator &lt;=&gt; 定义为默认值:

      #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;
      }
      

      【讨论】:

        猜你喜欢
        • 2021-11-07
        • 2021-06-14
        • 2021-07-20
        • 2012-12-21
        • 2018-06-11
        • 2012-03-07
        • 1970-01-01
        相关资源
        最近更新 更多