Подтвердить что ты не робот

Оператор выполнения <=> для опционального <T>

С добавлением operator<=> в С++ 20 я хотел попытаться объяснить, как реализовать этот оператор для тех случаев, когда это не простое сравнение по элементам.

Как бы вы реализовали оператор космического корабля для сравнения optional<T> с optional<U> или U, это случай, когда нам нужно сравнить T с U или сравнить базовые состояния, получив правильный тип возврата? Не существует такого примера в последней статье.

4b9b3361

Ответ 1

Я верю, что правильным способом реализовать это будет использование шаблона функции std::compare_3way() для обработки как (1), является ли такое сравнение жизнеспособным, и (2) какова категория сравнения.

Это делает реализацию всех операторов сравнения довольно компактной:

template <typename T>
class optional {
public:
    // ...

    template <typename U>
    constexpr auto operator<=>(optional<U> const& rhs) const
        -> decltype(compare_3way(**this, *rhs))
    {
        if (has_value() && rhs) {
            return compare_3way(**this, *rhs);
        } else {
            return has_value() <=> rhs.has_value();
        }
    }

    template <typename U>
    constexpr auto operator<=>(U const& rhs) const
        -> decltype(compare_3way(**this, rhs))
    {
        if (has_value()) {
            return compare_3way(**this, rhs);
        } else {
            return strong_ordering::less;
        }
    }

    constexpr strong_ordering operator<=>(nullopt_t ) const {
        return has_value() ? strong_ordering::greater
                           : strong_ordering::equal;
    }
};

Трехстороннее сравнение bool дает std::strong_ordering, которое неявно конвертируется в другие четыре категории сравнения.

Аналогично, strong_ordering::less неявно конвертируется в weak_ordering::less, partial_ordering::less, strong_equality::unequal или weak_equality::nonequivalent, если это необходимо.