使用 C++20 结构体的 Spaceship 运算符澄清 std::weak_ordering

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

我正在学习 C++20 中的

std::strong_ordering
std::weak_ordering
。根据文档,
std::strong_ordering
要求等效值无法区分,而不是
std::weak_ordering

在研究

std::weak_ordering
时(特别是在宇宙飞船运算符
<=>
的背景下)
,我通常会遇到类似下面的例子,它代表一个乘法表达式:

// Represents a multiplication expression, the result of which is (multiplicand * multiplier)
struct Multiplication {
    int multiplicand;
    int multiplier;
};

这个结构体看起来应该是弱排序的,因为不同对的被乘数和乘数可以计算出相同的结果,这意味着等效值可以区分(Multiplication{3, 2}、Multiplication{6, 1}和乘法{1, 6} 从技术上讲都代表 6)。

但是,比较不同乘法结构体的简单方法实际上会返回

std::strong_ordering
,因为乘法结果是整数,因此是强有序的。

struct Multiplication {
    int multiplicand;
    int multiplier;

    // This actually returns std::strong_ordering by default
    auto operator<=>(MultiplicationExpression rhs) const 
    {
        return (multiplicand * multiplicator) <=> (rhs.multiplicand * rhs.multiplicator);
    }
};

在这种情况下,我有责任将返回类型显式注释为

std::weak_ordering
以使其在语义上准确吗?

c++ operator-overloading c++20 spaceship-operator
1个回答
0
投票

根据文档,

std::strong_ordering
要求等效值不可区分,这与
std::weak_ordering
相反。

这是不正确的。它需要“可替代性”,在标准中定义为:

每当

f(a) == f(b)
为 true 时
a == b
为 true 的属性,其中
f
表示仅读取可通过参数的公共 const 成员访问的比较显着状态的函数。

这是一个非常狭隘的定义,允许

a
b
在数据上存在差异,只要它们不是“比较显着的”。

话虽这么说:

在这种情况下,我有责任将返回类型显式注释为

std::weak_ordering
以使其在语义上准确吗?

是的。编译器无法知道什么是“可替代的”,什么是不可替代的。这是一个语义属性,始终由程序员来定义。

是的,你的

Multiplication
结构是不可替代的。

请注意,解决此问题很容易:

std::weak_ordering operator<=>(MultiplicationExpression rhs) const = default;

您甚至不必定义该函数。

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