C++高阶:元编程(Metaprogramming)--入门篇

模板元编程(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、"值"元函数: 模板传参是'值'

cpp 复制代码
#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 constexpr int value = M;
};


int main() {
    // 3.元函数的调用 通过::访问类模板的成员
    int value=gcd<12,6>::value; // 值作为模板参数  
    cout << value << endl;      // 输出 6
}

2、"类型"元函数: 模板传参是'类型',普通函数做不到

cpp 复制代码
#include <iostream>
using namespace std;

// 功能:返回给定类型数组的维度
// 主模板, struct 可以换成 class + public:
template< typename T >
struct dim { static constexpr size_t value = 0u;}; // 当类型不是数组类型时,返回0

// 特化1: 递归也可以放在特化中,而不一定在主模板中
template< typename U, size_t N >
struct dim< U[N] > { static constexpr size_t value = 1u + dim< U >::value; };
// 特化2
template< typename U >
struct dim< U[] > { static constexpr size_t value = 1u + dim< U >::value; };

int main() {
    using array_t = int[10][20][30]; // 类型别名
    int arrry_dim = dim<array_t>::value; // 类型作为模板参数
    cout << "维度 = " << arrry_dim << endl; // 维度 = 3
}

对上面的优化版(这种更常见)

cpp 复制代码
// 标准库中有一个值叫 value 的静态成员常量元函数
template <typename T, T v> struct integral_constant { static constexpr T value = v; /*....*/ };

// 下面几个继承 integral_constant, 就有静态成员 value 了
template <typename T>
struct dim : integral_constant<std::size_t, 0u> {};

template <typename U, std::size_t N>
struct dim <U[N]> : integral_constant<std::size_t, 1u + dim<U>::value > {};

template <typename U>
struct dim <U[]>  : integral_constant<std::size_t, 1u + dim<U>::value > {};

3、"类型"元函数: 模板返回值是'类型',普通函数做不到

cpp 复制代码
// 功能:返回移除 const 限定符的相同类型
template<typename T>
struct remove_const { 
    using type = T; // 没有const 正常返回
};

template<typename T>
struct remove_const<T const> { 
    using type = T; // 移除了const 的相同类型
};

对上面的优化版(这种更常见)

cpp 复制代码
template <typename T> struct type_is { using type = T; };   // 返回传入的类型, 统一命名 type

// 下面几个继承 type_is, 就有 type 了
template <typename T> struct remove_const: type_is< T > {}; // 没有 const 正常返回
template <typename T> struct remove_const<T const> : type_is< T > {}; // 移除了 const 的相同类型
// 举一反三:下面是 移除顶层 volatile 限定符
template <typename T> struct remove_volatile: type_is< T > {}; // 没有 volatile 正常返回
template <typename T> struct remove_volatile<T volatile> : type_is< T > {}; // 移除了 volatile 的相同类型

二、模板中 if-else 逻辑

三、模板中 for 逻辑

相关推荐
兵哥工控2 分钟前
MFC模拟量转工程量换应用程序实例
c++·mfc·工程量·模拟量
不会代码的小猴6 分钟前
C++的第十三天笔记
c++·笔记·算法
OliverH-yishuihan12 分钟前
Windows上VScode编译C++
c++·vscode
木心爱编程30 分钟前
Qt C++ Excel 文件解析与导出实战:QAxObject 封装工具类
c++·qt·数据库开发
爱装代码的小瓶子31 分钟前
【c++知识铺子】map和set的底层-红黑树
java·开发语言·c++
雪域迷影35 分钟前
macOS中使用cJSON解析库解析JSON
c++·macos·json·c·cmake·pkg-config
江湖人称贺行风38 分钟前
C++八股
c++·八股
枫叶丹441 分钟前
【Qt开发】Qt窗口(八) -> QFileDialog 文件对话框
c语言·开发语言·数据库·c++·qt
qq_479875431 小时前
深入解析 Protobuf 消息的分帧 (Framing) 与编码 (Codec)
linux·c++
chenyuhao20241 小时前
Linux系统编程:进程控制
linux·运维·服务器·开发语言·c++·后端