为啥 std::rel_ops::operators 在 C++20 中会被弃用?

Posted

技术标签:

【中文标题】为啥 std::rel_ops::operators 在 C++20 中会被弃用?【英文标题】:Why will std::rel_ops::operators be deprecated in C++20?为什么 std::rel_ops::operators 在 C++20 中会被弃用? 【发布时间】:2018-09-23 13:26:59 【问题描述】:

根据cppreference.com,std::rel_ops::operator!=,>,<=,>= 将在 C++20 中被弃用。

背后的原理是什么?

【问题讨论】:

可能是因为C++20采用了三路比较。 这能回答你的问题吗? Why is operator!= removed in C++20 for many standard library types? 【参考方案1】:

C++20 提供Three way comparison,因此不推荐使用唯一的。

【讨论】:

【参考方案2】:

在 C++20 中,您会得到 three-way comparison(运算符 <=>),如果提供,它会自动“生成”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 相比,三路比较有多个优点,这可能就是不推荐使用std::rel_ops 运算符的原因。在我的头顶上:

它更加通用,因为根据operator&lt;=&gt; 的返回类型(std::strong_orderingstd::weak_ordering,...),只会生成相关的运算符。有关详细信息,请参阅 &lt;compare&gt; 标头。

using namespace std::rel_ops 不会带来一堆模板化的运算符重载。

你可以让编译器默认为你生成三向运算符(auto operator&lt;=&gt;(A const&amp;) = default)——这基本上会生成基类和非静态数据成员的字典比较,另外它会推断如果返回类型是auto,则正确的排序类型。

【讨论】:

无法自拔,但“宇宙飞船操作员”听起来比“三路比较”要酷得多:P 据我了解,在大多数情况下甚至没有必要实现&lt;=&gt;。相反,一个人将能够写std::strong_ordering operator&lt;=&gt;(const TotallyOrdered&amp; that) const = default; @sv90 是的,你是对的,我在优势列表中添加了一个项目符号 ;) 如果文档巧妙地命名为 " != =="[1],则不会从 "operator" 获得 "operator==",除非 operator 是默认。 [1] 可以翻译成 Python 为“__cmp__ is not __eq__” 好吧,我没有对特定文档进行任何实际引用。 “[1]”是对如何阅读同一注释中的标题的诙谐 Python“翻译”的引用。我只是不知道 cmets 不保留稍微破坏了笑话的换行符。如果有兴趣,实际文档是P1185R1【参考方案3】:

背后的原理是什么?

rel_ops 已被 Library Support for the Spaceship (Comparison) Operator 弃用。论文没有列出任何动机,但确实出现在spaceship paper:

这包含命名空间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&lt;=&gt; 绝对优越:

确实有效。 您只需编写一个函数 (&lt;=&gt;) 而不是两个函数(==&lt;) 通常,您实际上必须编写零函数 (= default) 我提到它确实有效吗?

【讨论】:

以上是关于为啥 std::rel_ops::operators 在 C++20 中会被弃用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?