2017-12-24 10 views
0

내가 가지고있는 constexpr 만드는 데 사용되는 라이브러리에서 클래스와 다음 부동 소수점 숫자의 고정 소수점 표현 관리 : 나는 'Sublcass의 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; 
}; 

을 두 번째 - 마지막 블록에서 IntegerType, floatdouble에 대한 사용자 정의 변환 연산자를 제외하고 실질적으로 동등하게 동작하는 UFixed의 하위 클래스를 상속을 사용하여 정의하는 방법이 있는지 궁금합니다. explicit.

이 내 요구 사항에 작동하는 것 같다 또한 기본 클래스로 "constexpr"클래스
+0

흠, 내가 볼 수 없습니다. 당신은 무엇을 시도 했습니까? 어떻게 깨졌습니까? – Quentin

+0

@Quentin 예 : "double foo = bar;"를 시도하면 bar는 type이 UFixed 인 곳입니다. <8, 8>; '알려진 전환 없음'오류가 발생합니다. "double foo = static_cast (bar);" 괜찮아. 근본적인 문제는 lib가 작은 실수를 저장하기 위해 복소수를 사용하는 일부 코드의 드롭 인 대체 코드라는 것입니다. 코드를 통해 모든 할당을 캐스팅해야만 작동합니다. 나는 표현의 한계를 이해하고 안전상의 관점에서 보았을 때 좋았지 만 지금은 그렇게하지 않는 편이 좋다.) – Bitrex

+0

변환을 정수형으로 캐스팅하고 문제가되는 함수로 전달하는 것이 실제로 더 필요하다. 기본 유형은 typedefed이므로 할당 및 논리 목적을 위해 float, double 또는 다른 표현이 될 수 있지만 "double"만 허용하는 여러 함수로 전달 될 수 있어야합니다. 명시 적으로 던져야하는 것과 동일한 문제가 발생합니다. – Bitrex

답변

0

: 왜 당신은 할 수 없었다

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); 
    } 
}; 
관련 문제