这个元编程如何编译?

Joh*_*0te 2 c++ template-meta-programming

这是维基百科中显示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
}
Run Code Online (Sandbox Code Playgroud)

我理解它是如何工作的,递归地创建具有N的模板参数值的Factorial类型,直到找到特化<0>,这允许编译器解析链上的值.

我的问题是:编译后如何看待这个?编译器最终会产生类似于:

int x = 24;
int y = 1;
Run Code Online (Sandbox Code Playgroud)

或者结果会更复杂?我问,因为我想知道它是否基本上导致:

Factorial<4>::value
Run Code Online (Sandbox Code Playgroud)

被可执行代码中的常量(24)替换,或者它更复杂.我只想弄清楚这有助于在已完成的程序中提高效率,所以这会有很大的帮助:)

AnT*_*AnT 9

是的,它们被简化为即时编译时值.一个更有说服力的例子就是这样的

int a[Factorial<4>::value];
Run Code Online (Sandbox Code Playgroud)

要么

struct S {
  int a : Factorial<4>::value;
};
Run Code Online (Sandbox Code Playgroud)

要么

switch (a) {
  case Factorial<4>::value: ;
}
Run Code Online (Sandbox Code Playgroud)

即语言需要常量编译时值的上下文.如果Factorial<4>::value不是立即编译时常量,则这些示例都不会编译.


Mic*_*urr 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:
Run Code Online (Sandbox Code Playgroud)

和 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
Run Code Online (Sandbox Code Playgroud)

所以答案是他们将元编程归结为最终结果。

请注意,我什至没有使用任何优化标志。