21

ここでコードを見つけましたループや条件なしで 1 から 1000 を印刷しています

誰かがコンパイル時の再帰がどのように機能するかを説明してもらえますか、Googleで見つけることができませんでした

// compile time recursion
template<int N> void f1()
{ 
    f1<N-1>(); 
    cout << N << '\n'; 
}

template<> void f1<1>() 
{ 
    cout << 1 << '\n'; 
}


int main()
{
    f1<1000>();
}

ありがとうございました!

4

5 に答える 5

12

(呼び出しなど)f1<N>の値を減らしてテンプレートを繰り返しインスタンス化します。の明示的な特殊化は再帰を終了します。1になるとすぐに、コンパイラーはテンプレート化された関数ではなく、特殊化された関数を選択します。Nf1<N>()f1<N-1>N==1N

f1<1000>()コンパイラがf1<N>999回インスタンス化するようにします(への最後の呼び出しではカウントされませんf1<1>)。これが、テンプレートメタプログラミング技術を多用するコードのコンパイルに時間がかかる理由です。

全体はコンパイラの最適化スキルに大きく依存しています。理想的には、再帰(forテンプレートを使用してループをエミュレートするためのハックとしてのみ機能します)を完全に削除する必要があります。

于 2011-03-11T14:32:42.310 に答える
2

概念的には、実行時の再帰とほぼ同じように機能します。f1<1000>呼び出しf1<999>てから1000を出力します。f1<999>呼び出しf1<998>てから999などを出力します。1になると、テンプレートの特殊化が再帰を中止するための基本ケースとして機能します。

于 2011-03-11T14:32:49.277 に答える
1

非常に単純ですが、各テンプレートのインスタンス化により、変更されたパラメーターを使用して新しい関数が作成されます。定義した場合と同様に、f1_1000()、f1_999()など。

各関数は、名前が1つ少ない関数を呼び出します。f1_1()を定義するための再帰的ではない別のテンプレートがあるため、ストップケースもあります。

于 2011-03-11T14:33:05.913 に答える
1

これは、純粋なコンパイル時の再帰であるとは限りません。コンパイラはf1()、2 から 1000 までのすべてのパラメーター値に対して関数をインスタンス化する必要があり、それらは互いに呼び出します。

cout << ...次に、コンパイラは、これらの呼び出しを一連のステートメントに変換できることを確認する場合があります。呼び出しがなくなるかもしれませんが、そうでないかもしれません - これはコンパイラ次第です。C++ の観点からすると、これは一連の関数呼び出しであり、コンパイラは動作を変更しない限り、何でもできます。

于 2011-03-11T14:45:28.640 に答える
1

ここで階乗計算の説明があります。

ところで、あなたの関数は負の数では機能しないことに注意してください。

于 2011-03-11T14:47:41.603 に答える