【C++基础知识】C++ 模板元编程(Template Metaprogramming, TMP)技术详解
模板元编程技术随着 C++ 标准的演进不断发展,以下是各技术及其引入版本的详细说明:
1. 基础模板技术(C++98/03 时代)
(1) 类型萃取(Type Traits)
- 引入版本:部分在 C++98,完整化于 C++11
<type_traits>
- 示例:
// C++11 static_assert(std::is_integral<int>::value, ""); // C++11 static_assert(std::is_integral_v<int>); // C++17 引入 _v 后缀
(2) SFINAE(Substitution Failure Is Not An Error)
- 引入版本:C++98(标准未明确命名,但支持该行为)
- 标准化工具:
std::enable_if
(C++11)std::void_t
(C++17)
(3) 递归模板(Recursive Templates)
- 引入版本:C++98(经典模板元编程基础)
- 示例:
// C++98 编译期阶乘计算 template<int N> struct Factorial { static const int value = N * Factorial<N-1>::value; };
(4) 特化与偏特化(Specialization)
- 引入版本:C++98
- 用途:针对特定类型定制模板行为
template<typename T> struct Foo; // 主模板 template<> struct Foo<int> { ... }; // 全特化 (C++98) template<typename T> struct Foo<T*> { ... }; // 偏特化 (C++98)
2. 现代模板技术(C++11/14/17)
(5) 可变参数模板(Variadic Templates)
- 引入版本:C++11
- 关键语法:
template<typename... Args>
- 示例:
// C++11 可变参数模板 template<typename... Args> void print(Args... args);
(6) 折叠表达式(Fold Expressions)
- 引入版本:C++17
- 语法:
(args + ...); // 一元右折叠 (C++17) (..., print(args)); // 逗号折叠 (C++17)
(7) constexpr
增强
- C++11:基础
constexpr
函数constexpr int square(int x) { return x * x; } // C++11
- C++14:放宽限制(支持局部变量、循环等)
constexpr int factorial(int n) { // C++14int res = 1;for (int i = 1; i <= n; ++i) res *= i;return res; }
- C++17:
if constexpr
(编译期分支)template<typename T> auto get_value(T t) {if constexpr (std::is_pointer_v<T>) return *t; // C++17else return t; }
(8) 变量模板(Variable Templates)
- 引入版本:C++14
- 示例:
template<typename T> constexpr bool is_pointer_v = std::is_pointer<T>::value; // C++14
3. 高级模式与编译期计算(C++11/14/17)
(9) CRTP(Curiously Recurring Template Pattern)
- 引入版本:模式在 C++98 已有实践,标准化应用在 C++11(如
std::enable_shared_from_this
)
(10) 标签分发(Tag Dispatching)
- 引入版本:C++98(基于特化),与
constexpr if
(C++17)结合更强大// C++17 结合 if constexpr template<typename T> void process(T x) {if constexpr (std::is_integral_v<T>) fast_path(x);else slow_path(x); }
(11) 编译期字符串(Compile-Time String Processing)
- 基础:C++11(
constexpr
函数) - 增强:C++17(
constexpr
lambda、非类型模板参数扩展)// C++17 编译期字符串哈希 template<size_t N> constexpr size_t hash(const char (&s)[N]) {size_t res = 0;for (size_t i = 0; i < N; ++i) res ^= s[i];return res; }
4. 现代替代方案(C++20)
(12) Concepts
- 引入版本:C++20
- 用途:替代 SFINAE,约束模板参数
template<typename T> concept Integral = std::is_integral_v<T>; // C++20template<Integral T> void foo(T x); // 更清晰的约束
(13) constexpr
容器与算法
- 引入版本:C++20
- 示例:
constexpr std::vector<int> v = {1, 2, 3}; // C++20 constexpr auto sum = std::accumulate(v.begin(), v.end(), 0);
(14) 非类型模板参数扩展
- C++17:允许
auto
非类型参数template<auto N> struct Foo { }; // C++17 Foo<42> f1; Foo<'a'> f2;
- C++20:支持浮点数、类类型等
template<std::floating_point T> struct Bar; // C++20
版本总结表
技术 | 引入版本 | 关键改进版本 |
---|---|---|
类型萃取 | C++98 | C++11 (<type_traits> ) |
SFINAE | C++98 | C++11 (std::enable_if ) |
递归模板 | C++98 | — |
可变参数模板 | C++11 | C++17 (折叠表达式) |
constexpr 函数 | C++11 | C++14/C++17/C++20 |
折叠表达式 | C++17 | — |
CRTP | C++98 | C++11 (标准化应用) |
Concepts | C++20 | — |
编译期字符串 | C++11 | C++17 (增强) |
if constexpr | C++17 | — |
演进趋势
- C++98/03:基础模板元编程(递归、特化)
- C++11/14:现代化(可变参数、
constexpr
、类型萃取) - C++17:简化(折叠表达式、
if constexpr
) - C++20:革命性改进(Concepts、
constexpr
容器)
现代 C++ 更倾向于使用 constexpr
和 Concepts 替代传统 TMP,但经典技术仍是底层库设计的核心工具。