double でテンプレートメタプログラミング
double は非型テンプレートパラメータに使えないので,そのコンパイル時計算は constexpr 関数に頼るのが一般的だと思いますが,テンプレートでもやってやれないことはありません.
// 有名な階乗の計算を double で行います // Gamma function ではありません template <double const &d, bool Continue = (d > 0.9)> struct fact { static constexpr double prior = d - 1.0; // ローカル変数 static constexpr double value = d * fact<prior>::value; }; template <double const &d> struct fact<d, false> { static constexpr double value = 1.0; }; // constexpr double fact_ten = fact<10.0>::value; // 参照型のテンプレート引数には static storage duration を持つオブジェクトしか渡せません // constexpr double ten = 10.0; // これは g++ 4.6.0 と clang 2.9 ではテンプレート引数に渡せません // N3126 以前のドラフトでは,external linkage が要求されているからだと思われます // extern constexpr double ten = 10.0; // これでもいいのですが,ヘッダに書くと ODR をぶち壊すので好きではありません // こうしましょう struct values { static constexpr double ten = 10.0; }; constexpr double fact_ten = fact<values::ten>::value; static_assert(fact_ten == 3628800.0, ""); // たぶん成功します
double に限らず,literal type なら何でも扱うことができます.
Temporary object を使えないのが不便に感じますが,コメントで示したように,関数で言うローカル変数にあたるものを自然に作ることができるので,constexpr 関数に対して劣る点ばかりではないと思います.
一方,constexpr 関数には実行時でもそのまま使えるという利点があります.もっとも,コンパイル時に計算可能な実装が必ずしも実行時に最適な実装になるわけではないので,そのメリットは限られるようにも思えます.