我一直在阅读有关 C++20 的一致比较(即operator<=>
)的一些内容,但无法理解std::strong_ordering
和之间的实际区别是什么std::weak_ordering
(_equality
这种方式的版本也是如此)。
除了对类型的可替代性进行非常详细的描述之外,它实际上是否会影响生成的代码?它是否为如何使用该类型添加了任何约束?
希望看到一个真实的例子来证明这一点。
2 回答
它是否为如何使用该类型添加了任何约束?
一个非常重要的限制(原始论文没有打算这样做)是采用这不再是这种情况,因为非类型模板参数不再以这种方式工作(请参阅P1907R0以了解问题的解释和P1907R1以了解新规则的措辞)。strong_ordering
P0732 的重要性作为指示类类型可以用作非类型模板参数的指标。weak_ordering
由于模板等效性必须如何工作,因此对于这种情况是不够的。
通常,有可能某些算法只需要weak_ordering
而其他算法需要strong_ordering
,因此能够在类型上注释它可能意味着编译错误(提供的强排序不足),而不是简单地在运行时未能满足算法的要求,因此只是未定义行为。但是我所知道的标准库和 Ranges TS 中的所有算法都只需要weak_ordering
. 我不知道有哪一个需要strong_ordering
我的头脑。
它实际上会影响生成的代码吗?
在需要的情况之外strong_ordering
,或者算法根据比较类别明确选择不同的行为,没有。
真的没有任何理由拥有std::weak_ordering
。确实,该标准根据“严格”弱顺序描述了诸如排序之类的操作,但是在严格弱顺序和原始集合的完全有序划分为不可比较等价类之间存在同构。很少遇到对顺序结构(将每个等价类视为一个“值”)和一些可能更精细的等价概念感兴趣的通用代码:请注意,当标准库使用<
(或<=>
)时,它不使用==
(这可能会更好)。
的通常示例std::weak_ordering
是不区分大小写的字符串,因为例如打印两个仅按大小写不同的字符串肯定会产生不同的行为,尽管它们是等价的(在任何运算符下)。然而,尽管存在许多类型,但它们可能具有不同的行为==
:例如,两个std::vector<int>
对象可能具有相同的内容和不同的容量,因此附加到它们可能会以不同的方式使迭代器无效。
一个简单的事实是,由std::strong_ordering::equivalent
而不是由std::weak_ordering::equivalent
隐含的“平等”与从中受益的代码无关,因为泛型代码不依赖于隐含的行为变化,非泛型代码不需要区分排序类型,因为它知道它所操作的类型的规则。
该标准试图通过谈论“可替代性”来赋予区别意义,但这不可避免地是循环的,因为它可以明智地仅指代通过比较检查的状态。这是在发布 C++20 之前讨论过的,但是(可能出于显而易见的原因)没有进行太多计划中的进一步讨论。