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 逻辑

相关推荐
古月-一个C++方向的小白5 小时前
C++11之lambda表达式与包装器
开发语言·c++
tanyongxi667 小时前
C++ AVL树实现详解:平衡二叉搜索树的原理与代码实现
开发语言·c++
斯是 陋室9 小时前
在CentOS7.9服务器上安装.NET 8.0 SDK
运维·服务器·开发语言·c++·c#·云计算·.net
tju新生代魔迷10 小时前
C++:list
开发语言·c++
HHRL-yx10 小时前
C++网络编程 5.TCP套接字(socket)通信进阶-基于多线程的TCP多客户端通信
网络·c++·tcp/ip
tomato0910 小时前
河南萌新联赛2025第(一)场:河南工业大学(补题)
c++·算法
每一天都要努力^13 小时前
C++拷贝构造
开发语言·c++
NoirSeeker14 小时前
在windows平台上基于OpenHarmony sdk编译三方库并暴露给ArkTS使用(详细)
c++·windows·arkts·鸿蒙·交叉编译
落羽的落羽14 小时前
【C++】(万字)一文看懂“类与对象”
c++
闻缺陷则喜何志丹15 小时前
【带权的并集查找】 P9235 [蓝桥杯 2023 省 A] 网络稳定性|省选-
数据结构·c++·蓝桥杯·洛谷·并集查找