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

问题描述 投票:0回答:3

根据 cppreference.com

std::rel_ops::operator!=,>,<=,>=
将在 C++20 中弃用。

背后的理由是什么?

c++ standards deprecated std c++20
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
    .

  • 则排序

14
投票

背后的理由是什么?

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
    )
  • 我有没有提到它确实有效?

3
投票

C++20 提供了三路比较,因此唯一的比较将被弃用。

© www.soinside.com 2019 - 2024. All rights reserved.