API для упаковки и распаковки значений

Это класс, представляющий экспоненту. Его основная цель – иметь дело с логарифмическими величинами.

template<std::floating_point Representation>
class Exponent
{
    public:
        using representation = Representation;

        struct Literal{};

        constexpr explicit Exponent(representation val, Literal):m_val{val}
        {}

        constexpr explicit Exponent(representation val):m_val{std::log2(val)}
        {}

        constexpr representation value() const
        {
            return m_val;
        }

        constexpr operator representation() const
        {
            return std::exp2(m_val);
        }

        constexpr Exponent& operator+=(Exponent other)
        {
            m_val += other.m_val;
            return *this;
        }

        constexpr Exponent& operator-=(Exponent other)
        {
            m_val -= other.m_val;
            return *this;
        }

        constexpr Exponent& operator/=(Exponent other)
        {
            m_val /= other.m_val;
            return *this;
        }

        constexpr Exponent& operator*=(Exponent other)
        {
            m_val *= other.m_val;
            return *this;
        }

        constexpr auto operator<=>(Exponent const&) const = default;

    private:
        representation m_val;
};

template<std::floating_point T>
constexpr Exponent<T> operator+(Exponent<T> a, Exponent<T> b)
{
    return a+=b;
}

//...

Я не уверен в том, как правильно устранить неоднозначность между операциями преобразования данных (логарифм против экспоненты) и чистыми преобразованиями значений (простое присваивание).

Другой вопрос, должен ли API имитировать реальные значения. С помощью вышеуказанного API:

constexpr double multiply(double a, double b)
{return Exponent{a} + Exponent{b};}

static_assert(multiply(2.0, 3.0) == 6.0);

Однако, если вы определяете оператор * для показателей степени как сложение, вы вместо этого просто напишите:

constexpr double multiply(Exponent a, Exponent b)
{return a*b;}

static_assert(multiply(2.0, 3.0) == 6.0);

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *