模板元编程

模板元编程

广义的元编程是指为生成代码进行的编程,例如词法/语法编译器flex/bison可根据自定义语言生成词法及语法解释器C语言代码,这可算入广义元编程的范畴

在C++中,元编程专指针对类型以及常数进行推导、演算和构造等操作,这些操作的共同特点都是面向编译期逻辑,大多通过模板技巧实现,是一种狭义的元编程。

helloworld

/**
 * @brief 元编程helloworld 
 * @filename meta_demo.cpp
 */
#include <iostream>
#include <cstdint>


template <uint64_t N>
struct Factorial {
    //enum { Value = N * Factorial<N-1>::Value };
    static const uint64_t Value = N * Factorial<N-1>::Value;
};

template<>
struct Factorial<1> {
    //enum { Value = 1 };
    static const uint64_t Value = 1;
};

int TestFactorial()
{
    auto fact7 = Factorial<7>::Value;
    auto fact23 = Factorial<23>::Value;

    return 0;
}

int main(int argc, char *argv[]) {
    TestFactorial();
    return 0;
}

复习编译过程

预编译

# -E,只执行到预编译。直接输出预编译结果
gcc -E hello.c -o hello.i

编译

# -S,只执行到源代码到汇编代码的转换,输出汇编代码。
gcc -S hello.i -o hello.s
# 或者
gcc -S hello.c -o hello.s

汇编

# -c,只执行到编译,输出目标文件。
gcc -c hello.s -o hello.o
# 或者
gcc -c hello.c -o hello.o

链接

TODO: 待补充

验证编译期求值

进行验证fact7fact23的数值是编译器进行计算出来的:

g++ -S meta_demo.cpp -o meta_demo.s

	.file	"meta_demo.cpp"
	.text
	.section	.rodata
	.type	_ZStL19piecewise_construct, @object
	.size	_ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
	.zero	1
	.local	_ZStL8__ioinit
	.comm	_ZStL8__ioinit,1,1
	.text
	.globl	_Z13TestFactorialv
	.type	_Z13TestFactorialv, @function
_Z13TestFactorialv:
.LFB1522:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movq	$5040, -16(%rbp)
	movabsq	$8128291617894825984, %rax
	movq	%rax, -8(%rbp)
	movl	$0, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1522:
	.size	_Z13TestFactorialv, .-_Z13TestFactorialv
	.globl	main
	.type	main, @function
main:
.LFB1523:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movq	%rsi, -16(%rbp)
	call	_Z13TestFactorialv
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1523:
	.size	main, .-main
	.type	_Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB2004:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	%edi, -4(%rbp)
	movl	%esi, -8(%rbp)
	cmpl	$1, -4(%rbp)
	jne	.L7
	cmpl	$65535, -8(%rbp)
	jne	.L7
	leaq	_ZStL8__ioinit(%rip), %rdi
	call	_ZNSt8ios_base4InitC1Ev@PLT
	leaq	__dso_handle(%rip), %rdx
	leaq	_ZStL8__ioinit(%rip), %rsi
	movq	_ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
	movq	%rax, %rdi
	call	__cxa_atexit@PLT
.L7:
	nop
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE2004:
	.size	_Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
	.type	_GLOBAL__sub_I__Z13TestFactorialv, @function
_GLOBAL__sub_I__Z13TestFactorialv:
.LFB2005:
	.cfi_startproc
	endbr64
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$65535, %esi
	movl	$1, %edi
	call	_Z41__static_initialization_and_destruction_0ii
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE2005:
	.size	_GLOBAL__sub_I__Z13TestFactorialv, .-_GLOBAL__sub_I__Z13TestFactorialv
	.section	.init_array,"aw"
	.align 8
	.quad	_GLOBAL__sub_I__Z13TestFactorialv
	.hidden	__dso_handle
	.ident	"GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	 1f - 0f
	.long	 4f - 1f
	.long	 5
0:
	.string	 "GNU"
1:
	.align 8
	.long	 0xc0000002
	.long	 3f - 2f
2:
	.long	 0x3
3:
	.align 8
4:

求解斐波那契数列

template <uint64_t N>
struct Fibonacci  {
    static const uint64_t Value = Factorial<N-1>::Value + Factorial<N-2>::Value;
};

template<>
struct Fibonacci <1> {
    static const uint64_t Value = 1;
};

template<>
struct Fibonacci <0> {
    static const uint64_t Value = 0;
};

int TestFibonacci()
{
    auto fib10 = Fibonacci<10>::Value;
    auto fib45 = Fibonacci<45>::Value;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Erice_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值