[英]Is there a wrapper for floating point numbers in C++20 that would enable me to default the spaceship operator?
我正在觀看“使用 C++20 三路比較 - Jonathan Müller - Meeting C++ 2019”的演講,它提到了包含浮點成員的類的問題。
問題來自這樣一個事實,即涉及 NaN(s) 的 IEEE 754 比較很奇怪,並且不提供總排序。 Talk 提供了一種解決此問題的方法,例如在實現 <=> 時使用strong_order或手動忽略 NaN 值(假設值從不為 NaN)。
我的問題是,是否有一些庫包裝器可以讓我說“我保證”我的浮點數永遠不會是 NaN或者可以對浮點數進行緩慢但有效的比較(速度較慢但更安全,因為現在訂購了 NaN)。 我的目標是通過使成員浮動飛船友好(這樣我可以默認飛船)來避免手動實現飛船。
使用談話中的例子:
// original class
struct Temperature{
double value;
};
struct TemperatureNoNan{
std::a_number<double> value; // I promise value will never be NaN
// Now spaceship defaulting works
};
struct TemperatureStrongO{
std::s_ordered<double> value; // I want strong ordering(2 diff NaNs are not the same)
// Now spaceship defaulting works
};
“我保證”我的浮點數永遠不會是 NaN
template <std::floating_point T>
struct NeverNaN {
T val;
constexpr NeverNaN(T val) : val(val) { }
constexpr operator T() const { return val; }
constexpr bool operator==(NeverNaN const&) const = default;
constexpr std::strong_ordering operator<=>(NeverNaN const& rhs) const {
auto c = val <=> rhs.val;
assert(c != std::partial_ordering::unordered);
return c > 0 ? std::strong_ordering::greater :
c < 0 ? std::strong_ordering::less :
std::strong_ordering::equal;
}
};
不幸的是,沒有像這樣“提升”比較類別的好方法。 而且目前優化得不是很好。
這將對浮點數進行緩慢但有效的比較(較慢但更安全,因為現在訂購了 NaN)
這個通過std::strong_order()
或std::weak_order()
[cmp.alg]具有特定的庫支持,具體取決於您想要的比較類型:
template <std::floating_point T>
struct TotallyOrdered {
T val;
constexpr TotallyOrdered(T val) : val(val) { }
constexpr operator T() const { return val; }
// depends on whether or not you want == NaN to still be false?
// might need to be: return (*this <=> rhs) == 0;
constexpr bool operator==(TotallyOrdered const&) const = default;
constexpr auto operator<=>(TotallyOrdered const& rhs) const {
return std::strong_order(val, rhs.val);
// ... or std::weak_order(val, rhs.val)
}
};
標准庫中沒有這方面的內容,但實現起來很簡單:
template<class T,class O=std::weak_ordering>
struct a_number {
T t;
O operator<=>(const a_number &rhs) const {
return t<rhs.t ? O::less : t==rhs.t ? O::equivalent : O::greater;
}
};
template<class T>
struct s_ordered {
T t;
auto operator<=>(const s_number &rhs) const {
return std::strong_order(t,rhs.t);
}
};
...使用任何其他轉換運算符或其他所需的便利。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.