1

私は最近、C++でテンプレートのメタプログラミングを始めており、いくつかの基本機能をそれぞれの再帰的コンパイル時テンプレート定義に変換しようとしています。例えばC++は再帰的なクラス定義をどのように扱いますか?

template <typename T, T A, unsigned int N> 
class pow { enum : T { value = A * pow<T, A, N-1>::value } }; 
template <typename T, T A> class pow<T, A, 0> { enum : T { value = 1 } }; 

構文とテンプレートの力が私を驚かせます。しかし、1つの質問は私を悩ましています: C++はどのようにそれらの再帰的定義を扱いますか?より具体的に(賢明な資源)

または:

  • コンパイラが(/どのようにメモリが割り当てられている)列挙値を含むテンプレートクラスのインスタンスの作成をどのように処理します

  • 生成されたすべてのクラスは、コンパイル後にメモリに残っているのですか、またはトップクラス(クリーンアップ)のみを保持するコンパイラによって最適化されていますか?

  • RAMに依存しない最大の再帰的な深さはありますか(コンパイラー自身の制限事項)?

このような構造の標準編集に関する詳細な説明は高く評価されます。

+3

を警告する "最大の再帰の深さは...どのあり、" _: '-ftemplate-深さを有する++グラム=参照N'ます。https://gcc.gnu .org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#C_002b_002b-Dialect-Options –

+0

これはcurrenrly 1024です。しかし、それはコンパイラの制約か慣例なのか(これまでのC++標準では17が奇妙な選択だったので)? –

+1

コンパイラがインスタンス化された型をダンプすることは想像もできません。後で何度か使用されるかどうかを知る方法がないからです。リンクフェーズでは、ある種類のカリングが実行されます。そして、メタプログラミングでは、完全なものになることを期待しています。 – SoronelHaetir

答えて

1

pow::valueは、コンパイル時にconst expressです。コンパイラはpow<T, A, N>::valueA * pow<T, A, N - 1>::valueで計算します。 Aはまた、コンパイル時におけるconstの値であり、コンパイラはpow<T, A, N - 1>::value

...

計算pow<T, A, N - n>::value

計算pow<T, A, N - n - 1>::value

を計算し続ける...

コンパイラはutilのを停止しますプログラムが定義していたので、pow<T, A, 1>::valueを計算する必要はありません。pow<T, A, 1>::value = 1

int main() { 
    int value = pow<int, 1, -1>::value; 
} 

GCCコンパイラは、再帰的反復の最大値に達する前に、constの値を見つけるcould'tためである

fatal error: template instantiation depth exceeds maximum of xxx 

を警告する記述する場合。

コンパイル後、コンパイラはpow<T, A, N - n>::valueの値をimmediate numberとして保存しますが、中間値は維持されません。

int main() { 
    400546:  55      push %rbp 
    400547:  48 89 e5    mov %rsp,%rbp 
    ... 
    int a = pow<int, 2, 8>::value; 
    40055d:  c7 45 f0 00 01 00 00 movl $0x100,-0x10(%rbp) 
    ... 
} 

$0x100pow<int, 2, 8>::valueの結果です。この結果を保持する余分なアドレスはありません。

再帰深度の最大値は、特殊なコンパイラによって決定されます。たとえば、gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609デフォルトの最大値は900です。プログラマはこの値を-ftemplate-depthで設定できます。

ただし、-ftemplate-depthの値は、int32(2147483647)の最大値を超えることはできませんでした。

この構造では、再帰の深度もtype Tで制限される可能性があります。

int main() { 
    int result = pow<int, 2, 200>::value; 
} 

gccが_

error: overflow in constant expression [-fpermissive] 
関連する問題