キーワードを使用して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;
}
仕事?