如何在不将枚举实际存储在类属性之一的情况下知道使用了哪个枚举模板参数?

时间:2019-03-24 01:52:29

标签: c++ c++11

这不是我第一次打它。这次我在玩“二进制角度”类(无符号整数映射到0-360deg或0-180deg圆)。不同的对象跨越不同的范围。有时候是0-360,有些物体的角度是-180-+180。我希望将对象转换为度或弧度的“算术”值时自动完成。 我将“ span”的类型存储为该类的枚举属性,并且可以正常工作,但是我认为这是错误的。应该有静态测试该模板参数的方法。

我知道如何使用“ is_arithmetic”,“ is_unsigned”等静态检查。但是我找不到我想要的东西。

枚举声明:


enum cycle {
    FULL,            ///<  0 to 360deg
    HALF,            ///<  0 to 180deg
    FULL_SYMMETRIC,  ///<  -180deg to 180deg
    HALF_SYMMETRIC   ///<  -90deg to 90deg
};

类声明:

/// Binary angle representation with conversion to/from DEG and RAD
template<typename U = uint32_t, enum cycle c = FULL>
class angle {
    U bin_angle;
    static const enum cycle type = c;
public:

以及度数/弧度提取成员函数

    /// Get current value in degrees or, optionally, in radians represented
    /// by the floating point type D
    template<typename D>
    D get(enum angle_units au = DEG) const {
        static_assert(std::is_arithmetic<D>::value,
                      "The angle can only be requested as an arithmetic type");
        D circle_ang = cycle_span<D>(type);

        D ang = D(0);
        if (bin_angle != U(0)) {
            // XXX there must be a better way than to use long double
            long double ratio =
                    (long double) (maxU()) / (long double) (bin_angle);
            ang = (circle_ang) / D(ratio);
        }

        if (ang > cycle_end<D>(type)) {
            ang -= circle_ang;
        }

        if (au == RAD) {
            ang = deg2rad<D>(ang);
        }

        return ang;
    }

还有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

迈克尔·肯泽尔(Michael Kenzel)是对的-那是那些“大ah”时刻之一。代码已更改为

// Binary angle representation with conversion to/from DEG and RAD
template<typename U = uint32_t, enum cycle span = FULL>
class angle {
    U bin_angle;


public:

    /// Get current value in degrees or, optionally, in radians represented
    /// by the floating point type D
    template<typename D>
    D get(enum angle_units au = DEG) const {
        static_assert(std::is_arithmetic<D>::value,
                      "The angle can only be requested as an arithmetic type");
        D circle_ang = cycle_span<D>(span);

        D ang = D(0);
        if (bin_angle != U(0)) {
            // XXX there must be a better way than to use long double
            long double ratio =
                    (long double) (maxU<U>()) / (long double) (bin_angle);
            ang = (circle_ang) / D(ratio);
        }

        if (ang > cycle_end<D>(span)) {
            ang -= circle_ang;
        }

        if (au == RAD) {
            ang = deg2rad<D>(ang);
        }

        return ang;
    }

,它就像以前一样工作。我什至没有想到template参数可以用作属性或变量。