3

次のコードを見つけて動作しているように見えますが、まったく理解できません。Recursive Struct
のように見えますが、これは見たことがありません。

template<int B, int N>
struct Pow {
    enum{ value = B*Pow<B, N-1>::value };
};

template< int B >
struct Pow<B, 0> {
    enum{ value = 1 };
};
int quartic_of_three = Pow<3, 4>::value;

これは何ですか?

4

2 に答える 2

3

これは、必要な数のテンプレートの特殊化をサポートするコンパイラーに依存して、コンパイル時に積分累乗を計算する方法です (つまり、正確に移植可能なコードではありません)。

お気に入りの C++ テキスト ブックのテンプレートを読む

まだ C++ のテキスト ブックを持っていない場合: 必要な場合は、SO FAQ C++ ブック リストを参照してください。


C ++ 11でのはるかに優れた(数年以内に)おそらくはるかに移植性の高い方法は、constexpr関数を使用することです:

#include <iostream>
using namespace std;

constexpr int constpow( int base, int n )
{
    return (n == 0? 1 : base*constpow( base, n - 1 ));
}

int main()
{
    int const quarticOfThree = constpow( 3, 4 );
    wcout << quarticOfThree << endl;
}

ただし、これは、私がこれを書いているときの最新バージョンのVisual C++であるVisual C++ 11.0ではサポートされていません

于 2013-01-04T03:17:09.653 に答える
2

このテンプレート定義で注意すべき重要な点は次のとおりです。

  • テンプレートパラメータはであり、多くの人がテンプレートに通常期待するようなタイプではありません。
  • 構造体テンプレートのフィールドvalueは、これらのパラメーターから計算されます。
  • テンプレートには、でN設定した場合の2番目のパラメーターの部分的な特殊化があります0

お気づきのように、テンプレートはvalueフィールド計算で繰り返されます。部分的な特殊化が定義されていない場合、その再帰は無限になります。2番目のパラメータが「到達」したとき0、つまり。テンプレートのインスタンス化のネストに従って、最も外側の値フィールドを計算するために必要な連続する値フィールドを取得しようとすると、コンパイラは最終的に、パラメータNがに等しいテンプレートをインスタンス化する必要が0あり、定数を含む部分特殊化バージョンを選択します。フィールドの値1。次に、コンパイラはネストされた各値フィールドを計算して、最終的に最も外側のフィールドに戻ることができます。

この手法を使用すると、コンパイラーに特定の値をオフラインで(つまり、コンパイル時に)計算させることができます。これにより、プログラマーは定数値をハードコーディングしたり、コンパイルされたプログラムに実行ごとに計算させたりすることなく、パラメーターと式で定義することができます。

しかし、このアプローチの問題は、それがどれほど巧妙に見えるかもしれませんが、その読みやすさ、したがってメンテナンスの容易さです。これが、新しい標準が概念を提供する理由である可能性が最も高いconstexprです。これは、いわゆる純粋な計算を定義するための非常に適切な方法です。


テンプレートの両方のフィールドが署名されており、計算では負の値を処理しようとしないことに注意してください。Nが最初にに設定されて-1いる場合、結果は興味深いものになる可能性があります。

于 2013-01-04T04:02:31.260 に答える