Ответ 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
, если это необходимо.