0

キーワードを使用してconstexpr、コンパイル時に float または double に格納できる最大整数値を計算します (n は仮数部のビット数、val は最初は 1.0 です)。

constexpr double calc_max_float(int n, double val)
{
    return (n == 0) ? (val) : calc_max_float(n - 1, 2.0*val);
}

この値は、次のテンプレートで使用するために生成されます。

template <bool, class L, class R>
struct IF  // primary template
{
    typedef R type;
};

template <class L, class R>
struct IF<true, L, R> // partial specialization
{
    typedef L type;
};

template<class float_type>
inline float_type extract_float()
{
    return (extract_integer<typename IF<sizeof(float_type) == 4,
                                        uint32_t,
                                        uint64_t
                                       >::type
                           >() >> (8*sizeof(float_type) - std::numeric_limits<float_type>::digits))*(1./calc_max_float(std::numeric_limits<float_type>::digits, 1.0));
}

このテンプレートは、次と同等の 2 つの関数を生成します。

inline float extract_single()
{
    return (extract_integer<uint32_t>() >> 9) * (1./(8388608.0));
}
inline double extract_double()
{
    return (extract_integer<uint64_t>() >> 12) * (1./(67108864.0*67108864.0));
}

GCC ではすべて問題ありませんが、VC11/12 でもコンパイルできるようにしたいと思います。交換方法について何か考えはありますconstexpr calc_max_float(int n, double val)か?

編集:

明確にするために、テンプレートを使用してコンパイル時に定数 pow(2,x) を計算する方法を探しています。正しい方向へのポイントでさえ素晴らしいでしょう。

使用例として、関数 extract_integer(type min, type range) があり、これは符号付きまたは符号なしの型で動作します。float または double 型の値 [0,1) を返す関数 extract_float() を作成しようとしています。

私は次のようなものを探していると思います:

template <const unsigned  N, const uint64_t val>
inline uint64_t calc_max_float()
{
    return calc_max_float<N - 1,2*val>();
}

template <const uint64_t val>
inline double calc_max_float<0, val>()
{
    return (double) val;
}

ただし、関数の部分的な特殊化は許可されていませんか? そして、私たちがそれに取り組んでいる間、なぜ次のようなものではないでしょうか

template <const unsigned  N, const uint64_t val>
inline uint64_t calc_max_float()
{
    return (N != 0) ? calc_max_float<N - 1,2*val>() : val;
}

仕事?

4

1 に答える 1