23

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

背后的原理是什么?

4

3 回答 3

28

在 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

于 2018-04-13T08:43:45.363 回答
13

背后的原理是什么?

rel_ops已被Spaceship (Comparison) Operator 的库支持弃用。该论文没有列出任何动机,但它确实出现在了宇宙飞船论文中:

这包含 namespace std::rel_ops,因此我们建议也删除(或弃用)std::rel_ops

论文中提到了四个原因(包括正确性和性能)。但是两篇论文中都没有提到的一个重要问题是std::rel_ops……只是……行不通。经验法则是使用 ADL 找到运算符。rel_ops没有给你 ADL-findable 运算符,它只是声明不受约束的函数模板,如:

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<=>严格来说是优越的:

  • 它确实有效。
  • 您只需编写一个函数 ( <=>) 而不是两个 ( ==and <)
  • 通常,您实际上必须编写零个函数 ( = default)
  • 我提到它真的有效吗?
于 2018-04-23T15:12:47.203 回答
3

C++20 提供了三路比较,因此不推荐使用唯一的比较。

于 2018-04-13T08:45:27.233 回答