8

テンプレート関数のパラメーターから非型のテンプレート パラメーターを推測することは可能ですか?

次の単純なテンプレートを検討してください。

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の追加でしょうか?

4

7 に答える 7

9

現在のコードは通常、次のように記述されると思います。

constexpr factorial (int n)
{
    return n > 0 ? n * factorial( n - 1 ) : 1;
}

などの定数式で呼び出すと、factorial(5)すべてのコンパイラの魔法が作用します。しかしint a = 3; factorial(a)、そうすると、従来の関数にフォールバックすると思います-つまり、事前に計算された回答のルックアップテーブルを作成しません。

一般に、できるかのように、すべての関数とコンストラクターをマークする必要がありconstexprます。何も失うことはありません。必要に応じて、コンパイラはそれを通常の関数として扱います。

于 2012-01-12T15:09:54.207 に答える
7

タイムマシンが無いと出来ません。

関数へのパラメーターは実行時に処理されます。はい、あなたの場合、それはリテラル定数ですが、それは特殊なケースです。

関数定義では、パラメーターの型はコンパイル時に固定されます (したがって、テンプレート パラメーターを推測するために使用できます) が、パラメーターは実行時にのみ固定されます。

なぜこれが必要なのですか?を入力しなくてもいいようにするためです<>か?

于 2012-01-12T15:01:46.070 に答える
1

あなたにはそれができないと思います。これを行う唯一の方法は、テンプレート バージョンのパラメータconstexprとして渡される関数パラメータを持つことですが、関数パラメータは認められません。templatefactorialconstexpr

于 2012-01-12T15:01:27.997 に答える
1

いいえ、できません。テンプレート引数は、一般にコンパイル時に認識されないvalueではなく、関数引数のからのみ推測できます。

もちろん、factorial非テンプレートconstexpr関数として書き直すこともできます。引数がわかっている場合は、コンパイル時に評価されます。

于 2012-01-12T15:02:43.930 に答える
0

邪悪なマクロを使用します。

#define factorial(X) factorial<X>()
于 2016-05-25T00:47:10.887 に答える
0

いいえ、巨大な switch ステートメントを作成したい場合を除き、それは不可能です:

int getFactorial( const int v )
{
  switch ( v )
  {
    case 1 : return factorial<1>();
    case 2 : return factorial<2>();
    //etc
    default:
       ;
  }
  return 0;
}
于 2012-01-12T15:01:47.830 に答える