Реализующий оператор<=> для необязательного<T>

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

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

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

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

Точно так же, strong_ordering::less будучи неявно конвертируемым в weak_ordering::less, partial_ordering::less, strong_equality::unequal, или же weak_equality::nonequivalentв зависимости от обстоятельств.

Другие вопросы по тегам