![](/img/trans.png)
[英]How does a parser for C++ differentiate between comparisons and template instantiations?
[英]Why does spaceship allow mixed comparisons (different template instantiations) with nonsense results?
編輯:這與宇宙飛船無關。 只是使用 spaceship 混淆了我的代碼中的真正問題(有關詳細信息,請參閱答案)。
我對這個程序的 output 感到驚訝:(如果您喜歡謎題,請隨時打開 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;
}
output:
錯誤的
錯誤的
錯誤的
錯誤的
在指責 Godbolt 緩存之后......我發現問題在於我正在比較TotallyOrdered<float>
和TotallyOrdered<double>
(在1234.567
之后添加f
會產生預期的輸出)。 我的問題是:
strong_order
<=>
,但當我進行混合比較時,我似乎得到了部分順序。std::strong_ordering
結果)編譯,防止給出std::partial_ordering
的比較? 這是允許的,因為您到T
的轉換運算符不明確。 這允許比較的雙方進行用戶定義的轉換為各自的T
。 所以你最終得到一個float
和一個double
。 然后它們都可以轉換為double
並且可以進行比較。 但該比較返回std::partial_ordering
,而不是std::strong_ordering
。
請注意, std::strong_ordering
可以與 bool 進行比較,這就是您的代碼首先編譯的原因。 雖然 cppreference.com 確實注意到:
嘗試將 strong_ordering 與 integer 文字 0 以外的任何內容進行比較的程序的行為未定義。
我不是 100% 確定您的程序是否正在顯示未定義的行為,或者是否有更多的轉換/促銷“魔術”正在進行。
無論哪種方式,如果您將轉換運算符更改為顯式,代碼將不再編譯。 我猜這是你真正想要的?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.