【发布时间】:2021-06-14 20:56:09
【问题描述】:
考虑以下两个重载operator<=> 为S:
#include <compare>
struct S {};
int operator<=>(S, int) { return 0; } #1
S operator<=>(S, S) { return {}; } #2
如果我将对象S 与int 进行比较,#1 将为我生成正确的运算符,因此像S{} <= 0、0 < S{} 或0 <=> S{} 这样的表达式将只是fine。
但是如果我将一个对象 S 与另一个对象 S 进行比较:
S{} < S{};
然后这将被重写为(S{} <=> S{}) < 0。由于(S{} <=> S{}) 将返回另一个S,我们回到原点问题:S 与int 比较。目前,我们没有operator<(S, int),所以#1 会为我生成正确的运算符。
但令人惊讶的是,三个编译器都没有对我这样做。 GCC、Clang 和 MSVC all 拒绝 S{} < S{} 并显示相同的错误消息:
no match for 'operator<' (operand types are 'S' and 'int')
这让我很沮丧。由于#1 确实存在。为什么这里没有发生操作符的嵌套生成?标准是怎么说的?是否存在静态约束违规?
【问题讨论】:
-
您的代码在这两种情况下都不合法。
<=>必须返回auto、std::strong_ordering、std::weak_ordering、std::partial_ordering或bool。 en.cppreference.com/w/cpp/language/default_comparisons -
只需将
<=>(S,S)的返回类型更改为auto,符合标准(据我所知),您仍然会得到相同的行为。 -
@NathanOliver 这仅适用于默认比较(
bool不适用于<=>)。 -
在链接页面(来自@NathanOliver)的下方进一步查看自定义比较器的返回类型“...有三种可用的返回类型:...”跨度>
-
@RichardCritten 我不确定这是否意味着这些是 only 可能的返回类型。至少,我在标准中找不到限制这一点的相关措辞。
标签: c++ language-lawyer c++20 spaceship-operator