gpt4 book ai didi

c++ - 为可选实现运算符<=>

转载 作者:IT老高 更新时间:2023-10-28 22:14:58 25 4
gpt4 key购买 nike

operator<=>被添加到 C++20 中后,我想尝试推理如何在那些不是简单的成员比较的情况下实现此运算符。

您将如何实现用于比较 optional<T> 的宇宙飞船运算符到 optional<U>U ,在这种情况下,我们要么必须比较 TU或比较基础状态,获得正确的返回类型? latest paper 中没有这样的例子.

最佳答案

<=>我们必须做出决定:如果我们需要的底层比较还没有实现 <=>,我们想做什么? ?

一个选项是:不在乎。只需使用 <=>如果相关类型没有提供,我们就没有可比性。这使得实现非常简洁(请注意,您需要对 == 执行相同的操作,总共六个函数):

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

template <typename U>
constexpr std::compare_three_way_result_t<T, U>
operator<=>(optional<U> const& rhs) const
{
if (has_value() && rhs) {
return **this <=> *rhs;
} else {
return has_value() <=> rhs.has_value();
}
}

template <typename U>
constexpr std::compare_three_way_result_t<T, U>
operator<=>(U const& rhs) const
{
if (has_value()) {
return **this <=> *rhs;
} else {
return strong_ordering::less;
}
}

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

bool 之间的三路比较s 产量 std::strong_ordering ,它可以隐式转换为其他比较类别。同样,strong_ordering::less可隐式转换为 weak_ordering::less , partial_ordering::less , strong_equality::unequal , 或 weak_equality::nonequivalent , 作为适当的。

以上是 super 好,快乐的答案。希望随着时间的推移,人们会采用<=>越来越多的代码将能够依赖于快乐的答案。


另一种选择是:我们确实关心,并希望退回到综合排序。也就是说,如果我们需要比较一个 TU他们不提供<=> ,我们可以使用标准库中新的自定义点对象之一。还是哪一个?最保守的选择是合成一个partial_orderingcompare_partial_order_fallback .这保证了我们总能得到正确的答案。

对于 optional<T>optional<U>比较,看起来像:

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

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

// ...
};

不幸的是,如上所述,我们的比较现在总是返回 partial_ordering -- 甚至在两个 optional<int> 之间s。所以更好的选择可能是使用任何<=>否则返回并使用保守的后备。我还不知道如何命名这个概念,所以我就直接说吧:

template <typename T, std::three_way_comparable_with<T> U>
constexpr auto spaceship_or_fallback(T const& t, U const& u) {
return t <=> u;
}

template <typename T, typename U>
constexpr auto spaceship_or_fallback(T const& t, U const& u)
-> decltype(std::compare_partial_order_fallback(t, u))
{
return std::compare_partial_order_fallback(t, u);
}

并使用它:

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

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

// ...
};

第三种选择,最保守的选择,是标准库将采用的。提供both关系运算符三向比较:

template <typename T> class optional { /* ... */ };

template <typename T, typename U>
constexpr bool operator<(optional<T> const&, optional<U> const&);
template <typename T, typename U>
constexpr bool operator>(optional<T> const&, optional<U> const&);
template <typename T, typename U>
constexpr bool operator<=(optional<T> const&, optional<U> const&);
template <typename T, typename U>
constexpr bool operator>=(optional<T> const&, optional<U> const&);

template <typename T, std::three_way_comparable_with<T> U>
std::compare_three_way_result_t<T, U>
operator<=>(optional<T> const& x, optional<U> const& y) {
if (x && y) {
return *x <=> *y;
} else {
return x.has_value() <=> y.has_value();
}
}

这是最保守的选项,因为它有效地采用了 C++17 及更早版本的比较实现策略 C++20 比较实现策略。如:“为什么不两者兼而有之?”战略。 concept的使用在 operator<=>是什么确保 a < b调用 <=>在可能的情况下,而不是 < .

这是迄今为止最乏味和最冗长的方法,有很多样板,但它确保对于现有的单对象比较类型,现有比较继续工作并做同样的事情。标准库必须像这样保守。

但新代码没有。

关于c++ - 为可选<T>实现运算符<=>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47315539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com