std::strong_ordering 如何只对零起作用?
How std::strong_ordering works only with zero?
我正在研究 three-way comparison 运算符 <=>
。我看到它 returns std::strong_ordering
。但是,我无法理解编译器如何在比较运算符(so<0
,而不是 so<1
)
中仅限制 0
#include<compare>
int main()
{
std::strong_ordering so = 55 <=> 10;
so < 0; // Fine
so < 1; // Fails
}
同样,so>20
也不起作用。以下也不起作用:
constexpr int Zero = 0;
so == Zero; // Error
so == 0; // Fine
EDIT - 有趣的观察(在 MSVC 编译器上)。以下是有效的:
so < nullptr
使用除文字 0
之外的任何内容与 std::strong_ordering
进行比较是明确的未定义行为,请参阅 C++20 草案的 [cmp.categories.pre]/3。
这取决于 compiler/standard 库如何或是否 enforced/diagnosed。
在没有任何编译器魔法的情况下实现 UB 诊断的一种方法是使用 std::nullptr_t
作为 std::strong_ordering
的重载比较运算符的参数(根据标准,它具有未指定的类型)。任何整数零文字都可以隐式转换为 std::nullptr_t
,但具有其他值的文字或不是文字的常量表达式则不能。参见 [conv.ptr]/1。
草稿说明中也提到了这种可能性。
Libc++ 似乎改为使用指向某些隐藏 class 的成员指针,参见 here。
Libstdc++ 似乎做了类似的事情,使用隐藏的 class 类型,需要从指向自身的指针构造,参见 here.
然而,这些实现都没有根据标准诊断导致 UB 的所有参数。特别是他们都接受 nullptr
作为没有诊断的参数:https://godbolt.org/z/esnvqR
我想对所有案例进行全面诊断需要一些编译器魔法。
我正在研究 three-way comparison 运算符 <=>
。我看到它 returns std::strong_ordering
。但是,我无法理解编译器如何在比较运算符(so<0
,而不是 so<1
)
0
#include<compare>
int main()
{
std::strong_ordering so = 55 <=> 10;
so < 0; // Fine
so < 1; // Fails
}
同样,so>20
也不起作用。以下也不起作用:
constexpr int Zero = 0;
so == Zero; // Error
so == 0; // Fine
EDIT - 有趣的观察(在 MSVC 编译器上)。以下是有效的:
so < nullptr
使用除文字 0
之外的任何内容与 std::strong_ordering
进行比较是明确的未定义行为,请参阅 C++20 草案的 [cmp.categories.pre]/3。
这取决于 compiler/standard 库如何或是否 enforced/diagnosed。
在没有任何编译器魔法的情况下实现 UB 诊断的一种方法是使用 std::nullptr_t
作为 std::strong_ordering
的重载比较运算符的参数(根据标准,它具有未指定的类型)。任何整数零文字都可以隐式转换为 std::nullptr_t
,但具有其他值的文字或不是文字的常量表达式则不能。参见 [conv.ptr]/1。
草稿说明中也提到了这种可能性。
Libc++ 似乎改为使用指向某些隐藏 class 的成员指针,参见 here。
Libstdc++ 似乎做了类似的事情,使用隐藏的 class 类型,需要从指向自身的指针构造,参见 here.
然而,这些实现都没有根据标准诊断导致 UB 的所有参数。特别是他们都接受 nullptr
作为没有诊断的参数:https://godbolt.org/z/esnvqR
我想对所有案例进行全面诊断需要一些编译器魔法。