samedi 23 mars 2019

How to tell which enum template parameter was used without actually storing that enum in one of the class attributes?

It is not the first time I hit it. This time I was playing with the "binary angle" class (unsigned integer is mapped into a 0-360deg or 0-180deg circle). Different object span on different ranges. Some times it is 0-360 and some objects angles are -180 - +180 . I want it be done automatically when the object is cast to "arithmetic" values in degrees0 or radians. I am storing the type of the "span" as an enum attribute of the class and it works, but I think it is wrong. There should be way to statically test that template parameter.

I know how to use static checks like "is_arithmetic", "is_unsigned", etc. But I can not find what I am looking for.

enum declaration:


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

class declaration:

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

and the degree/radians extraction member function

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

is there a better way?

Aucun commentaire:

Enregistrer un commentaire