非タイプのテンプレートパラメーターを推定します
-
27-10-2019 - |
質問
テンプレート関数パラメーターから非タイプのテンプレートパラメーターを推定することは可能ですか?
このシンプルなテンプレートを考えてみましょう。
template <int N> constexpr int factorial()
{
return N * factorial<N - 1>();
}
template <> constexpr int factorial<0>()
{
return 1;
}
template <> constexpr int factorial<1>()
{
return 1;
}
変えたいと思います factorial
代わりにこのように呼ぶことができるように:
factorial(5);
コンパイル時にnの値をコンパイラに把握させます。これは可能ですか?たぶん、いくつかの派手なC ++ 11の追加がありますか?
解決
タイムマシンがない限り、できません。
関数のパラメーターは実行時に処理されます。はい、で 君の ケースは文字通りの定数ですが、それは特別なケースです。
関数定義では、パラメーター 種類 コンパイル時間に固定されています(したがって、テンプレートパラメーターを推定するために使用できます)が、パラメーター 値 実行時にのみ固定されます。
なぜこれが必要なのですか?それはちょうどあなたがタイプする必要がないので <>
'じゃない?
他のヒント
あなたの現在のコードは通常、次のように記述されます、私は信じています:
constexpr factorial (int n)
{
return n > 0 ? n * factorial( n - 1 ) : 1;
}
あなたがそれを一定の発現で呼ぶ場合、 factorial(5)
, 、その後、すべてのコンパイラマジックが登場します。しかし、もしそうなら int a = 3; factorial(a)
, 、それから私はそれが従来の機能に戻るだろうと思います - つまり、それは事前に計算された答えのルックアップテーブルを構築していません。
一般に、すべての関数とコンストラクターを次のようにマークする必要があります constexpr
できれば。あなたは何も失いません、コンパイラは必要に応じて通常の関数としてそれを扱います。
私はあなたがそれをすることができるとは思わない。あなたができる唯一の方法は constexpr
次に渡される関数パラメーター template
のテンプレートバージョンのパラメーター factorial
, 、 しかし constexpr
関数パラメーターは認められません。
いいえ、巨大なスイッチステートメントを作成したくない限り、それは不可能です。
int getFactorial( const int v )
{
switch ( v )
{
case 1 : return factorial<1>();
case 2 : return factorial<2>();
//etc
default:
;
}
return 0;
}
いいえ、それはできません。テンプレート引数は、からのみ推測できます タイプ 関数引数の、ではありません 価値, 、一般的にコンパイル時には知られていません。
もちろん、書き直すことができます factorial
テンプレート以外として constexpr
関数;その後、引数が知られている場合、コンパイル時に評価されます。
邪悪なマクロを使用してください:
#define factorial(X) factorial<X>()