为什么 std::rel_ops::operators 在 C++20 中被弃用?
Why will std::rel_ops::operators be deprecated in C++20?
根据 cppreference.com,std::rel_ops::operator!=,>,<=,>=
将在 C++20 中弃用。
背后的原理是什么?
在 C++20 中,如果提供,您将得到 three-way comparison (operator <=>
), which automatically "generates" default comparisons:
struct A {
// You only need to implement a single operator.
std::strong_ordering operator<=>(const A&) const;
};
// Compiler generates 4 relational operators (you need to default the
// three-way comparison operator to get == and !=).
A to1, to2;
if (to1 > to2) { /* ... */ } // ok
if (to1 <= to2) { /* ... */ } // ok, single call to <=>
与 std::rel_ops
相比,three-way 有多个优点,这可能是 std::rel_ops
运算符被弃用的原因。在我的头顶上:
它更通用,因为,根据 operator<=>
的 return 类型(std::strong_ordering
、std::weak_ordering
、...),仅生成相关运算符。有关详细信息,请参阅 <compare>
header。
你不会通过 using namespace std::rel_ops
.
带来一堆模板化运算符重载
你可以让编译器默认为你生成three-way运算符(auto operator<=>(A const&) = default
)——这基本上会生成基[=47=的字典序比较] 和 non-static 数据成员,如果 return 类型是 auto
.
,它将推断出正确的排序类型
C++20 提供了 Three way comparison 因此唯一的将被弃用。
What's the rationale behind?
rel_ops
已被 Library Support for the Spaceship (Comparison) Operator. The paper doesn't list any motivation, but it does appear in the spaceship paper 弃用:
This subsumes namespace std::rel_ops
, so we propose also removing (or deprecating) std::rel_ops
.
论文中提到了四个原因(包括正确性和性能)。但是两篇论文中都没有提到的一个重要问题是 std::rel_ops
只是......不起作用。经验法则是使用 ADL 找到运算符。 rel_ops
不会为您提供 ADL 可查找的运算符,它只是声明不受约束的函数模板,例如:
namespace std {
namespace rel_ops {
template< class T >
bool operator!=( const T& lhs, const T& rhs )
{
return !(lhs == rhs);
}
}
}
所以使用像这样的算法:
struct X { ... };
bool operator<(X const&, X const&) { ... };
std::sort(values.begin(), values.end(), std::greater<>{});
只是行不通,除非您确保:
#include <utility>
using namespace std::rel_ops;
与您的第一个 include 一样,在任何地方都相当一致,以确保这些运算符在您可能调用的每个函数模板的定义点都可见。
所以 operator<=>
只是严格优越:
- 它确实有效。
- 你只需编写一个函数 (
<=>
) 而不是两个 (==
和 <
)
- 通常,您实际上必须编写零个函数 (
= default
)
- 我有提到它真的有效吗?
根据 cppreference.com,std::rel_ops::operator!=,>,<=,>=
将在 C++20 中弃用。
背后的原理是什么?
在 C++20 中,如果提供,您将得到 three-way comparison (operator <=>
), which automatically "generates" default comparisons:
struct A {
// You only need to implement a single operator.
std::strong_ordering operator<=>(const A&) const;
};
// Compiler generates 4 relational operators (you need to default the
// three-way comparison operator to get == and !=).
A to1, to2;
if (to1 > to2) { /* ... */ } // ok
if (to1 <= to2) { /* ... */ } // ok, single call to <=>
与 std::rel_ops
相比,three-way 有多个优点,这可能是 std::rel_ops
运算符被弃用的原因。在我的头顶上:
它更通用,因为,根据
operator<=>
的 return 类型(std::strong_ordering
、std::weak_ordering
、...),仅生成相关运算符。有关详细信息,请参阅<compare>
header。你不会通过
using namespace std::rel_ops
. 带来一堆模板化运算符重载
你可以让编译器默认为你生成three-way运算符(
auto operator<=>(A const&) = default
)——这基本上会生成基[=47=的字典序比较] 和 non-static 数据成员,如果 return 类型是auto
. ,它将推断出正确的排序类型
C++20 提供了 Three way comparison 因此唯一的将被弃用。
What's the rationale behind?
rel_ops
已被 Library Support for the Spaceship (Comparison) Operator. The paper doesn't list any motivation, but it does appear in the spaceship paper 弃用:
This subsumes namespace
std::rel_ops
, so we propose also removing (or deprecating)std::rel_ops
.
论文中提到了四个原因(包括正确性和性能)。但是两篇论文中都没有提到的一个重要问题是 std::rel_ops
只是......不起作用。经验法则是使用 ADL 找到运算符。 rel_ops
不会为您提供 ADL 可查找的运算符,它只是声明不受约束的函数模板,例如:
namespace std {
namespace rel_ops {
template< class T >
bool operator!=( const T& lhs, const T& rhs )
{
return !(lhs == rhs);
}
}
}
所以使用像这样的算法:
struct X { ... };
bool operator<(X const&, X const&) { ... };
std::sort(values.begin(), values.end(), std::greater<>{});
只是行不通,除非您确保:
#include <utility>
using namespace std::rel_ops;
与您的第一个 include 一样,在任何地方都相当一致,以确保这些运算符在您可能调用的每个函数模板的定义点都可见。
所以 operator<=>
只是严格优越:
- 它确实有效。
- 你只需编写一个函数 (
<=>
) 而不是两个 (==
和<
) - 通常,您实际上必须编写零个函数 (
= default
) - 我有提到它真的有效吗?