3

C++ テンプレートのメタプログラミングを表示するウィキペディアの例を次に示します。

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

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
    int x = Factorial<4>::value; // == 24
    int y = Factorial<0>::value; // == 1
}

特殊化が <0> になるまで、N のテンプレート パラメーター値を使用して Factorial の型を再帰的に作成する仕組みを理解しています。これにより、コンパイラーはチェーンの値を解決できます。

私の質問は次のとおりです。これはコンパイル後にどのように見えるでしょうか? コンパイラは文字通り、次のようなものを生成するだけになりますか?

int x = 24;
int y = 1;

または、結果はより複雑になりますか? 基本的に次の結果になるかどうか疑問に思っているので、私は尋ねています:

Factorial<4>::value

実行可能コードで定数 (24) に置き換えられているか、それよりも複雑な場合。これが完成したプログラムの効率にどのように役立つかを理解しようとしているだけなので、これは大いに役立ちます:)

4

5 に答える 5

9

はい、それらは即時のコンパイル時の値に縮小されます。よりわかりやすい例は次のようになります

int a[Factorial<4>::value];

また

struct S {
  int a : Factorial<4>::value;
};

また

switch (a) {
  case Factorial<4>::value: ;
}

つまり、言語がコンパイル時の定数値を必要とするコンテキストです。これらの例はFactorial<4>::value、即時コンパイル時の定数でない場合はコンパイルされません。

于 2011-08-30T17:09:57.353 に答える
5

さて、GCC から生成されたアセンブリは次のとおりです。

 ; command line used: gcc -c -S -fmasm-intel test.cpp

    .file   "test.cpp"
    .intel_syntax noprefix
    .text
.globl __Z3foov
    .def    __Z3foov;   .scl    2;  .type   32; .endef
__Z3foov:
LFB0:
    push    ebp
LCFI0:
    mov ebp, esp
LCFI1:
    sub esp, 16
LCFI2:
    mov DWORD PTR [ebp-4], 24
    mov DWORD PTR [ebp-8], 1
    leave
LCFI3:
    ret
LFE0:

そしてMSVC:

; command line used: cl -c /FAsc test.cpp

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

; removed soem excessive noise...

?foo@@YAXXZ PROC                    ; foo

; 16   : {

  00000 55       push    ebp
  00001 8b ec        mov     ebp, esp
  00003 83 ec 08     sub     esp, 8

; 17   :     int x = Factorial<4>::value; // == 24

  00006 c7 45 f8 18 00
    00 00        mov     DWORD PTR _x$[ebp], 24 ; 00000018H

; 18   :     int y = Factorial<0>::value; // == 1

  0000d c7 45 fc 01 00
    00 00        mov     DWORD PTR _y$[ebp], 1

; 19   : }

  00014 8b e5        mov     esp, ebp
  00016 5d       pop     ebp
  00017 c3       ret     0
?foo@@YAXXZ ENDP                    ; foo
_TEXT   ENDS
END

答えは、メタプログラミングを最終結果にまで煮詰めるということです。

最適化フラグも使用していないことに注意してください。

于 2011-08-30T17:10:14.610 に答える
3

コンパイラは文字通り、次のようなものを生成するだけになりますか?

はい。それが、このように何かをすることの要点です。

于 2011-08-30T17:07:12.833 に答える
2

私の質問は次のとおりです。これはコンパイル後にどのように見えるでしょうか? コンパイラは文字通り、次のようなものを生成するだけになりますか?

はい。Factorial<3>::value実際には定数式です。つまり、次のように書くこともできます。

const int M = Factorial<Factorial<3>::value>::value;
const int N = Factorial<Factorial<Factorial<3>::value>::value>::value;

そしてこれらも:

int array[Factorial<5>::value]; //its NOT a variable length array (VLA)
std::bitset<Factorial<5>::value> bits;

つまり、コンパイル時の定数が必要な場合はいつでも を使用できますFactorial<5>::value

于 2011-08-30T17:11:48.697 に答える
0

それらは確かに前者にまとめられています、

int x = 24;
int y = 1;

実際の制作プログラムでこのパターンを実際に使用することは難しいでしょうが...

于 2011-08-30T17:07:50.560 に答える