为什么 std::rel_ops:::运算符会在 C++20 中被弃用?
Why will std::rel_ops::operators be deprecated in C++20?
根据 cppreference.com,std::rel_ops::operator!=,>,<=,>=
将在C++20中被弃用。
背后的理由是什么?
在 C++20 中,您将获得三向比较(运算符<=>
),如果提供,它会自动"生成"默认比较:
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
相比,三向比较有很多优点,这可能就是弃用std::rel_ops
运算符的原因。在我的头顶上:
它更通用,因为根据
operator<=>
的返回类型(std::strong_ordering
、std::weak_ordering
、...),只生成相关的运算符。有关详细信息,请参阅<compare>
标头。您不会通过执行
using namespace std::rel_ops
带来一堆模板化的运算符重载。你可以要求编译器通过默认它(
auto operator<=>(A const&) = default
)为你生成三向运算符 — 这基本上会生成基类和非静态数据成员的字典比较,如果返回类型是auto
,它将推导出正确的排序类型。
背后的理由是什么?
rel_ops
已被宇宙飞船(比较)操作员的库支持弃用。这篇论文没有列出任何动机,但它确实出现在宇宙飞船的论文中:
这包含命名空间
std::rel_ops
,因此我们建议也删除(或弃用)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;
在任何地方都相当一致地包含您的第一个包含,以确保这些运算符在您可能调用的每个函数模板的定义点可见。
所以operator<=>
只是严格上级:
- 它确实有效。
- 你只需要写一个函数(
<=>
)而不是两个(==
和<
) - 通常,您实际上必须编写零个函数(
= default
) - 我有没有提到它确实有效?
> C++20 提供了三向比较,因此唯一的比较将被弃用。
- 用C++20 fmt限制结果的总大小
- 如何在C++20中创建模板别名的推导指南
- 实施具有 C++20 概念的配对概念
- C++20概念:需要运算符重载
- 为什么在C++20中对lambdas使用"std::bind_front"
- 填孔方法需要20分钟以上
- c++20[[no.unique_address]]中的新功能是什么
- 如何在 C++20 计时中为日期添加天数?
- 必须为 C++20 协程帧保留多少内存?
- C++20 概念:如何在"requires"子句中引用类名?
- 在C++中随机生成 20 个非重复数字
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- C++20 协程:需要一个使用 co_yield 的函数
- 主.cpp:18:20:错误:从"int*"转换为"int"会失去精度 [-fa
- 将 C++20 范围与istreambuf_iterator一起使用
- 使用文件系统时仍然需要链接到带有 C++20 的 stdc++fs?
- 在 C++20 中将多个范围适配器连接到一个范围中
- C++20 使用 Visual Studio 编译模块:不编译或导入 ixx 文件
- 标准::累积C++20版本
- 为什么 C++20 中的 [[可能]] 属性在这里引发警告?