9

我知道技术上的答案是:因为标准是这样说的。

但我对动机感到困惑:

我在默认情况下看不到任何“库” <=>:它可能会返回某种在技术上定义的类型,std但在某种意义上它是“假库”类型,编译器必须知道它,因为它必须能够默认operator <=>返回auto类型(更不用说好的编译器中指定的错误消息,<compare>所以很明显这里有一个语言<=>库链接)。

所以我知道有一些库功能可能需要我包含<compare>,但我不明白为什么默认<=>需要我包含该头文件,因为编译器无论如何都必须知道制作<=>.

注意:我知道大多数时候其他一些标准头文件会包含<compare>,这是一个关于语言/库设计的问题,而不是 C++ 强迫我在没有充分理由的情况下编写的额外一行。

4

1 回答 1

7

它可能会返回某种在技术上在 std 中定义的类型,但在某种意义上它是“假库”类型

好吧,<=>返回非常真实的类型,它们实际上是在<compare>其中定义和实现的。与使用初始值设定项列表构造 a 的方式相同std::initializer_list<T>,它实际上是在 中定义的真实类型<initializer_list>。而typeinfo<typeinfo>.

并且这些比较类型 - std::strong_orderingstd::weak_orderingstd::partial_ordering(最初也是std::strong_equalityand std::weak_equality) - 本身具有非平凡的转换语义和在它们上定义的其他操作,我们可能希望在未来进行更改。它们确实是非常特殊的语言类型,其中可转换性仅在一个方向上进行,但在某种程度上与继承非常不同(总排序类型只有三个值,但部分排序类型只有四个值......)。将这些定义为真正的库类型,然后将它们的交互指定为真正的库代码真的要容易得多。

该编译器必须知道它,因为它必须能够默认operator<=>返回auto类型

有点,但不是真的。编译器知道类型的名称是什么,以及如何为基本类型生成它们的值,但它实际上不需要知道更多。返回类型的规则基本上是根据底层成员返回的类型进行硬编码的<=>,不需要知道这些实际类型是什么样的。然后你只是在调用做......不管的函数。

必须包含标头的成本是键入#include <compare>然后解析它。编译器必须综合这些类型的成本是必须为每个 TU 支付的成本,无论它是否进行任何三向比较。另外,如果/当我们想要更改这些类型时,更改库类型比更改语言类型更容易。

于 2020-05-23T01:28:20.837 回答