簡體   English   中英

C++20 中是否有浮點數的包裝器可以讓我默認飛船運算符?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM