子类constexpr类获取不同的用户定义的转换行为

时间:2017-12-24 17:06:14

标签: c++ inheritance constexpr

我有一个来自库的constexpr类,用于创建和管理浮点数的定点表示:

template< unsigned Integer, unsigned Fraction >
class UFixed : FIXED_POINTS_DETAILS::UFixedBase< Integer, Fraction >
{
public:
    static_assert((Integer + Fraction) <= FIXED_POINTS_DETAILS::BitSize<uintmax_t>::Value, "Platform does not have a native type large enough for UFixed.");

public:
    using IntegerType = FIXED_POINTS_DETAILS::LeastUInt<Integer>;
    using FractionType = FIXED_POINTS_DETAILS::LeastUInt<Fraction>;
    using InternalType = FIXED_POINTS_DETAILS::LeastUInt<Integer + Fraction>;

    using ShiftType = FIXED_POINTS_DETAILS::LeastUInt<Integer + Fraction>;
    using MaskType = FIXED_POINTS_DETAILS::LeastUInt<Integer + Fraction>;

    constexpr const static uintmax_t IntegerSize = Integer;
    constexpr const static uintmax_t FractionSize = Fraction;
    constexpr const static uintmax_t LogicalSize = IntegerSize + FractionSize;
    constexpr const static uintmax_t InternalSize = FIXED_POINTS_DETAILS::BitSize<InternalType>::Value;

    constexpr const static uintmax_t Scale = 1ULL << FractionSize;

public:
    constexpr const static ShiftType IntegerShift = FractionSize;
    constexpr const static ShiftType FractionShift = 0;

    constexpr const static MaskType IntegerMask = FIXED_POINTS_DETAILS::IdentityMask<IntegerSize>::Value;
    constexpr const static MaskType FractionMask = FIXED_POINTS_DETAILS::IdentityMask<FractionSize>::Value;

    constexpr const static MaskType IdentityMask = (IntegerMask << IntegerShift) | (FractionMask << FractionShift);

    constexpr const static MaskType MidpointMask = FIXED_POINTS_DETAILS::MsbMask<FractionSize>::Value;
    constexpr const static MaskType LesserMidpointMask = MidpointMask - 1;

private:
    using Base = FIXED_POINTS_DETAILS::UFixedBase<Integer, Fraction>;
    using RawType = typename Base::RawType;

public:
    using Base::Base;

    constexpr UFixed(void);
    constexpr UFixed(const IntegerType & integer);
    constexpr UFixed(const IntegerType & integer, const FractionType & fraction);

    constexpr InternalType getInternal(void) const;
    constexpr IntegerType getInteger(void) const;
    constexpr FractionType getFraction(void) const;

    constexpr explicit operator IntegerType(void) const;
    constexpr explicit operator float(void) const;
    constexpr explicit operator double(void) const;

    template< unsigned IntegerOut, unsigned FractionOut >
    constexpr explicit operator UFixed<IntegerOut, FractionOut>(void) const;

    constexpr static UFixed fromInternal(const InternalType & value);

    UFixed & operator ++(void);
    UFixed & operator --(void);
    UFixed & operator +=(const UFixed & other);
    UFixed & operator -=(const UFixed & other);
    UFixed & operator *=(const UFixed & other);
    UFixed & operator /=(const UFixed & other);

public:
    constexpr const static UFixed Epsilon = UFixed::fromInternal(1);
    constexpr const static UFixed MinValue = UFixed::fromInternal(0);
    constexpr const static UFixed MaxValue = UFixed::fromInternal(~0);

    // 40 digits is probably enough for these
    constexpr const static UFixed Pi = 3.1415926535897932384626433832795028841971;
    constexpr const static UFixed E = 2.718281828459045235360287471352662497757;
    constexpr const static UFixed Phi = 1.6180339887498948482045868343656381177203;
    constexpr const static UFixed Tau = 6.2831853071795864769252867665590057683943;
};

我想知道是否有一种方法可以使用继承来定义UFixed的子类,除了IntegerType,{float的用户定义转换运算符之外,它的行为实质上等效。 1}},并且可以隐式应用倒数第二个块中的double,而不是explicit

1 个答案:

答案 0 :(得分:0)

这似乎符合我的要求,也是一个&#34; constexpr&#34; class作为基类:

template <unsigned Integer, unsigned Fraction>
struct MyUFixed : UFixed<Integer, Fraction>
{
   typedef UFixed<Integer, Fraction> fixed_point_t;
   using fixed_point_t::fixed_point_t; //pull in base constructors
   using typename fixed_point_t::IntegerType; //pull in "IntegerType"

   using fixed_point_t::operator double;
   using fixed_point_t::operator float;
   using fixed_point_t::operator IntegerType;

   constexpr MyUFixed(const fixed_point_t& other) :
   fixed_point_t(other) //constructor from base type
   {}

   //implicit conversions

   constexpr operator float() const
   {
      return static_cast<float>(*this);
   }

   constexpr operator double() const
   {
      return static_cast<double>(*this);
   }

   constexpr operator IntegerType() const
   {
      return static_cast<IntegerType>(*this);
   }
};