编辑:这与宇宙飞船无关。只是使用 spaceship 混淆了我的代码中的真正问题(有关详细信息,请参阅答案)。
我对这个程序的输出感到惊讶:(如果您喜欢谜题,请随时打开 Godbolt 链接并尝试自己找出原因)
#include <cstdint>
#include <cassert>
#include <compare>
#include <cmath>
#include <iostream>
#include <limits>
template<typename T>
struct TotallyOrdered
{
T val;
constexpr TotallyOrdered(T val) :
val(val) {}
constexpr operator T() const { return val; }
constexpr std::strong_ordering operator<=>(TotallyOrdered const& other) const
{
if (std::isnan(val) && std::isnan(other.val))
{
return std::strong_ordering::equal;
}
if (std::isnan(val))
{
return std::strong_ordering::less;
}
if (std::isnan(other.val))
{
return std::strong_ordering::greater;
}
if (val < other.val)
{
return std::strong_ordering::less;
}
else if (val == other.val)
{
return std::strong_ordering::equal;
}
else
{
assert(val > other.val);
return std::strong_ordering::greater;
}
}
};
int main()
{
const auto qNan = std::numeric_limits<float>::quiet_NaN();
std::cout << std::boolalpha;
std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) == std::strong_ordering::less) << std::endl;
std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) == std::strong_ordering::equal) << std::endl;
std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) == std::strong_ordering::equivalent) << std::endl;
std::cout << ((TotallyOrdered{qNan} <=> TotallyOrdered{1234.567}) == std::strong_ordering::greater) << std::endl;
}
输出:
假
假
假
假
在指责了Godbolt缓存之后......我发现问题在于我正在比较TotallyOrdered<float>
和TotallyOrdered<double>
(在给出预期输出f
之后添加)。1234.567
我的问题是:
- 为什么允许这样做?(不问这是否是标准行为;它是,但对设计意图感到好奇。)
- 为什么比较没有给出strong_ordering中的“枚举”?尽管我只定义了
strong_order
<=>
. - 如何强制仅“精确 +-cvref”比较(给出
std::strong_ordering
结果)编译,防止给出的比较std::partial_ordering
?