编辑:这与飞船无关。只是太空飞船的使用使我的代码中的真正问题变得模糊(请参阅答案以了解详细信息)。
我对该程序的输出感到惊讶:(如果您喜欢拼图,请随时打开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_order
<=>
。std::strong_ordering
编译(给出结果)的“精确+ -cvref”比较,阻止给出的比较std::partial_ordering
?之所以允许,是因为您的转化运算符toT
不明确。这样可以使比较的两面都经过用户定义的转换为各自的T
。因此,您最终得到afloat
和a double
。然后可以将它们都转换为double
可以进行比较。但是该比较返回std::partial_ordering
,而不是std::strong_ordering
。
请注意,std::strong_ordering
可以将其与bool进行比较,这就是为什么您的代码首先要编译的原因。尽管cppreference.com确实指出:
试图将strong_ordering与整数文字``0''以外的任何东西进行比较的程序的行为是未定义的。
我不是100%确定您的程序是否显示未定义的行为,或者是否还有更多的转换/促销“魔术”。
无论哪种方式,如果将转换运算符更改为显式的,则代码将不再编译。我猜您真正想要的是什么?
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句