C ++ 20中是否有浮点数的包装器,使我可以默认飞船运算符? [英] Is there a wrapper for floating point numbers in C++20 that would enable me to default the spaceship operator?

查看:85
本文介绍了C ++ 20中是否有浮点数的包装器,使我可以默认飞船运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在观看使用C ++ 20三向比较-JonathanMüller-Meeting C ++ 2019"的演讲,它提到了包含浮点成员的类的问题.

I was watching "Using C++20 three way comparison - Jonathan Müller - Meeting C++ 2019" talk and it mentioned problems with classes that contain floating point members.

问题来自这样一个事实,即涉及NaN的IEEE 754比较很奇怪,不能提供全部排序. Talk提供了解决此问题的方法,例如使用 strong_order 或在实现< =>时手动忽略NaN值(假设值永远不是NaN).

Problem comes from the fact that IEEE 754 comparisons involving NaN(s) are weird and do not provide total ordering. Talk gives a way to work around this problems, for example using strong_order or manually ignoring NaN values when implementing <=> (assuming that values are never NaN).

我的问题是,是否有一些库包装程序可以使我说我保证"我的浮动变量永远不是NaN ,它们会对浮动变量进行缓慢但有效的比较(比较慢但更安全) (因为现在已订购NaN).我的目标是通过使成员漂浮式飞船友好(这样我可以默认飞船)来避免手动执行飞船.

My questions is if there are some library wrappers that would enable me to say that "I promise" that my floats are never NaN or that would do slow but valid comparisons on floats(slower but safer since NaNs are now ordered). My goal is to avoid manual implementation of spaceship by making member float spaceship friendly(so I can default spaceship).

使用演讲中的示例:

// 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

"I promise" that my floats are never 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;
    }
};

不幸的是,没有办法提升"这样的比较类别.目前,它的优化效果不是很好.

Unfortunately, there's no good way to "lift" a comparison category like this. And it doesn't optimize very well at the moment.

这将对浮点数进行缓慢但有效的比较(由于现在已订购NaN,因此比较慢但更安全)

that would do slow but valid comparisons on floats(slower but safer since NaNs are now ordered)

该对象通过std::strong_order()std::weak_order()具有特定的库支持. [ cmp.alg] ,具体取决于您要进行的比较:

This one has specific library support by way of either std::strong_order() or std::weak_order() [cmp.alg] depending on what kind of comparison you want:

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)
    }
};

这篇关于C ++ 20中是否有浮点数的包装器,使我可以默认飞船运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆