模板元编程(Template Meta programming,TMP)
就是面向模板编程,把计算过程从运行时提前到编译期,提升性能;
区别于泛型编程(利用模板实现“安全的宏”)
应用场景: 编译期 数值计算、类型计算、代码循环展开
思考题:
用装饰器模式给存在已久的多个类(xx_config类)添加新功能: 读取 json/yaml/xml/ini 配置文件对应部分数据到本类私有成员(不同数量和类型)。就是用一句话添加新功能,注释这句话后,新功能消失
特点:
模板执行完全在编译期
操作的数据对象只能是常量(如enum,静态常量,基本数据类型,自定义数据类型),
不能是运行期的变量,不能用 if else for while;其计算能力受到具体编译器实现的限制(如递归嵌套深度,C++98 要求至少 17,C++11 要求至少 1024)
技巧:
- if-else逻辑可用 type_traits(类型特征)实现在编译期做判断,计算、查询、转换、选择
- for 逻辑可用递归、重载、继承、偏特化 实现
一、核心概念:元函数(不是一个函数,功能类似函数)
(根据模板传参分为:“类型type”元函数,“值value”元函数)
函数三要素:返回值,调用方式,参数
约定 :
对于’类型’元函数,将保存返回结果的类型别名用 ::type 命名
对于’值’元函数,将保存返回结果的静态成员用 ::value 命名
1、“值”元函数: 模板传参是‘值’
#include <iostream>
using namespace std;
// 功能:求两个数的最大公约数
// 主模板:递归调用(关键点1),class 可以换成 struct
template < unsigned M, unsigned N > // 1.元函数的参数: 模板参数
class gcd {
// 元函数(不是一个函数,元函数发生在编译期,而通常函数调用发生在运行时)
public:
static constexpr int value = gcd< N, M%N >::value; // 2.元函数的返回值:类模板的静态成员常量
};
// 特化模板:处理边界(关键点1)
template< unsigned M >
class gcd< M, 0 > {
public:
static_assert(M != 0);
static