Трехстороннее сравнение заменяет все остальные операторы сравнения, кроме ==? - PullRequest
2 голосов
/ 14 марта 2020

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

Что такое Я здесь скучаю?

Ответы [ 3 ]

5 голосов
/ 14 марта 2020

Я читал, что другие операторы больше не нужны (кроме ==).

Верно, , за исключением == - это бит ключа. Существует две категории операторов сравнения:

  • операторы равенства (==, !=)
  • операторы упорядочения (<=>, <, >, <=, >=)

В каждой из этих категорий первый из перечисленных мною (== и <=>) является оператором сравнения primary . Это единственный оператор, который вам нужно определить, если вы хотите включить эту категорию. Если вы хотите равенства, укажите ==. Если вы хотите заказать, укажите <=> (а также ==). Другие операторы сравнения - это вторичные операторы сравнения - выражения, использующие вторичное сравнение, в 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, если только у вас нет особой c потребности в них (а это не такая необходимость).

Подробнее см. Сравнения в С ++ 20 .

Единственное исключение из этого правила для удобства: если вы по умолчанию operator<=>, тогда вы также получите объявленное, дефолтное operator== , Это как если бы вы по умолчанию оба. В этом примере, поскольку ваши сравнения - это только сравнения по умолчанию для членов, вы могли бы написать:

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

Как объявление с одним оператором сравнения, которое будет вести себя так, как если бы вы написали:

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

Что дает вам правильный оператор равенства, необходимый для вашей программы.

2 голосов
/ 14 марта 2020

From cppreference :

Вкратце, класс, который определяет operator<=>, автоматически получает сгенерированные компилятором операторы <</strong>, <= </strong>, > и > = . Класс может определить operator<=> как значение по умолчанию, и в этом случае компилятор также сгенерирует код для этого оператора. "

Код для! = И == не генерируется, поэтому вам нужно осуществить сравнения.

0 голосов
/ 14 марта 2020

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...