[英]Why do empty structs in C++20 do not have implicit spaceship operator?
动机:有时我使用 std::variant 来实现“花式”枚举,其中一些枚举状态可以携带 state。
现在,如果我想将<=>
用于我的变体,它要求我的空结构已定义 <=>。 这对我来说似乎有点奇怪,因为如果类型有 0 位 state 则该类型的所有实例都是相同的。
完整示例:
#include <compare>
#include <iostream>
#include <variant>
struct Off{
// without this the code does not compile
auto operator<=>(const Off& other) const = default;
};
struct Running{
int rpm=1000;
auto operator<=>(const Running& other) const = default;
};
using EngineState = std::variant<Off, Running>;
int main()
{
EngineState es1, es2;
es1<=>es2;
}
默认的比较运算符是选择加入,而不是选择退出。
如果它是选择退出的,那么它可以将无法编译的代码转换为具有某种未知含义的编译代码。 标准委员会试图尽可能地保持向后兼容性。
其原因最终归结为:“可比较”类型意味着什么?
可比较的类型首先是带有值的类型。 这种类型的对象带有一个在某种意义上有意义的值。
你的例子就是这样一种情况。 本质上,您正在使用variant
和Off
来使用替代值来增加Running
的值状态。 我自己会使用optional<Running>
,但无论如何。 Off
是一种在您的问题空间中合法具有价值的类型。 它的价值是“不运行”。
大多数空的 object 类型并非如此。 根据该术语的任何定义, std::in_place_t
没有有意义的“价值”。 它是一个标签,用于将就地构造调用分派给某些类型的构造函数。 要求将一个实例与另一个实例进行比较是没有意义的。
但是,您希望在默认情况下使其具有可比性。
有很多无状态类型没有以面向值的方式使用。 用于分派到重载集的标签、用于提供对全局资源的基于对象的访问的类型等。这并不是说没有面向值的空类型。 但是它们太多了,单方面宣布它们都应该默认具有可比性似乎很奇怪。
此外,以价值为导向是可比性的必要条件,但它并不是充分的。 对于明显以价值为导向的类型,我们没有默认的可比性。
聚合类型具有所有公共成员,因此没有什么能阻止任何人随时在其中插入任何值。 他们显然是以价值为导向的。
然而聚合类型在默认情况下是不可比较的。 他们也不应该。 并非所有可以假设比较的东西都应该进行比较。
即使可以对特定的值集合进行排序,允许对它们进行排序是否有意义? 这取决于收藏。 如果我有 2D 点类型,可以订购。 但应该吗? 我可以理解平等测试,但全面的可比性? 你可以定义它,但这样的比较有意义吗?
这是只有类型的创建者才能回答的问题。 因此,我们强迫类型的创建者询问他们想要什么。
没有成员只是有一些公共成员的特例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.