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)替换,或者它更复杂.我只想弄清楚这有助于在已完成的程序中提高效率,所以这会有很大的帮助:)
是的,它们被简化为即时编译时值.一个更有说服力的例子就是这样的
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不是立即编译时常量,则这些示例都不会编译.
好吧,这是从 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)
所以答案是他们将元编程归结为最终结果。
请注意,我什至没有使用任何优化标志。