18

以下のように、メタプログラミングを使用してコンパイル時に合計を計算する非常に単純なテンプレート クラスを作成しています。

#include <iostream>

using namespace std;

template<int N>
class Sum
{
    public:
        enum {value = N + Sum<N-1>::value };
};

template<>
class Sum<0>
{
    public:
        enum {value = 0};
};


int main()
{
    cout << Sum<501>::value << endl;
}

興味深い点は次のとおりです。

  • Sum<500> 以下を印刷すると、正常に動作します
  • Sum<501> になると、コンパイルは次のように失敗しました。

    sum.cpp:9: Sum<500>' sum.cpp:9: instantiated fromSum<501> からインスタンス化された sum.cpp:22: ここからインスタンス化されました

    sum.cpp:9: エラー: 型Sum<1>' used in nested name specifier sum.cpp:9: error: enumerator value forの値が不完全で、整数定数ではありません

  • Sum<501> は Sum<1> のエラーを報告し、Sum<502> は Sum<2> のエラーを報告します。差は常に 2 です。コンパイラには 500 の制限リソースがあるようです。

これについて何か考えはありますか?そして、彼らはこの限界を破る方法ですか?

ありがとう。

編集:
ありがとう、要点はアルゴリズムではなく、コンパイラの制限です-合計を取得する簡単な方法があることは知っています:)

編集2:

  • gcc 4.6 + を使用すると、エラー メッセージがより役に立ちます。

    sum.cpp:9:14: エラー: テンプレートのインスタンス化の深さが最大の 1024 を超えています (最大値を増やすには -ftemplate-depth= を使用します) 'class Sum<1>' をインスタンス化しています<1024>' sum.cpp:9:14: 'Sum<1025>' からインスタンス化されました sum.cpp:22:22: ここからインスタンス化されました

そうです、ftemplate-depth を使用するのが正しい方法です。しかし、Windowsではどうですか?VC9.0 の上限は 499 で、テンプレートの深さを設定するオプションはないようです。こちらを参照してください

4

2 に答える 2

16

GCC を使用している場合は、テンプレートの再帰の深さを で設定できます-ftemplate-depth=X。ここXで、 は必要な深さです。

g++ ...... -ftemplate-depth=750

これは、任意に高く設定できる単なる制限ではないことに注意してください。ある時点で、OS とハードウェアの制限に遭遇します。

実際の合計関数に関しては、最初の N 個の正の整数の合計に対するよく知られた分析解があります。

(つまりn*(n+1)/2)

于 2012-09-05T08:59:09.260 に答える
15

附属書 B は、推奨される最小制限を指定します。再帰的にネストされたテンプレートのインスタンス化の場合、推奨される最小制限は 1024 です。実装には 500 の制限があるようです。推奨される最小制限は単なるガイドラインであるため、これは依然として準拠しています。

コンパイラには、再帰的にネストされたテンプレートのインスタンス化の制限を増やすためのコマンド ライン フラグまたはその他のオプションがある場合があります。

最も簡単な修正は、非再帰アルゴリズムを使用することです。あなたの場合、

template<int N>
class Sum
{
    public:
        enum {value = N * (N + 1) / 2 };
};
于 2012-09-05T09:01:08.920 に答える