我正在学习 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
以使其在语义上准确吗?
根据文档,
要求等效值不可区分,这与std::strong_ordering
相反。std::weak_ordering
这是不正确的。它需要“可替代性”,在标准中定义为:
每当
为 true 时f(a) == f(b)
为 true 的属性,其中a == b
表示仅读取可通过参数的公共 const 成员访问的比较显着状态的函数。f
这是一个非常狭隘的定义,允许
a
和 b
在数据上存在差异,只要它们不是“比较显着的”。
话虽这么说:
在这种情况下,我有责任将返回类型显式注释为
以使其在语义上准确吗?std::weak_ordering
是的。编译器无法知道什么是“可替代的”,什么是不可替代的。这是一个语义属性,始终由程序员来定义。
是的,你的
Multiplication
结构是不可替代的。
请注意,解决此问题很容易:
std::weak_ordering operator<=>(MultiplicationExpression rhs) const = default;
您甚至不必定义该函数。