C++ 模板快速学习:从基础到高级
作者:暴走的小蜗牛
时间:2025年7月1日
标签:C++模板、泛型编程、元编程、CRTP、SFINAE、Concepts、模板元函数
目录
一、编写目标
C++ 模板是其最强大也是最复杂的语法功能之一,元编程、类型推导、类型演算、静态多态都基于模板技术实现。这篇博客从基础到高级全面分析 C++ 模板,给出一条可行的学习途径。
二、模板学习路线图
以下是基于简单→复杂→元编程→ C++20 的模板技术进阶途径:
三、基础语法结构
3.1 函数模板
template<typename T>
T add(T a, T b) {
return a + b;
}
typename
可以用class
- T 为类型参数,在函数使用
- 类似于 macro 编程,但安全性更好
3.2 类模板
template<typename T>
class Box {
public:
Box(T val) : value(val) {}
T get() const { return value; }
private:
T value;
};
展示:
Box<int> intBox(42);
Box<std::string> strBox("hello");
四、模板特化与偏特化
4.1 全特化
template<>
class Box<int> {
public:
Box(int v) : value(v * 10) {}
int get() const { return value; }
private:
int value;
};
4.2 偏特化
template<typename T, typename U>
class Pair {};
template<typename T>
class Pair<T, int> {
// U 特化为 int 时特化行为
};
五、SFINAE 与 enable_if 编译期类型选择
5.1 基础示例
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
safe_add(T a, T b) {
return a + b;
}
5.2 分析
enable_if<condition, type>
在 condition=false 时以编译失败选择后处理- 在组合 overload 时很有效
5.3 应用: 分类处理
template<typename T>
typename std::enable_if<std::is_floating_point<T>::value>::type
print(T v) { std::cout << "float: " << v << std::endl; }
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
print(T v) { std::cout << "int: " << v << std::endl; }
六、类型 traits 技术
6.1 常规示例
if constexpr (std::is_pointer<T>::value) {
// 按照指针处理
} else {
// 普通值
}
6.2 自定义 traits
template<typename T>
struct is_vector : std::false_type {};
template<typename T, typename A>
struct is_vector<std::vector<T, A>> : std::true_type {};
七、C++20 Concepts
7.1 概念
#include <concepts>
template<typename T>
requires std::integral<T>
T half(T x) {
return x / 2;
}
7.2 自定义 Concept
template<typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
};
八、模板元编程 TMP
8.1 递归 Fibonacci
template<int N>
struct Fib {
static constexpr int value = Fib<N-1>::value + Fib<N-2>::value;
};
template<> struct Fib<1> { static constexpr int value = 1; };
template<> struct Fib<0> { static constexpr int value = 0; };
static_assert(Fib<5>::value == 5);
8.2 编译期 if
template<typename T>
void check() {
if constexpr (std::is_same<T, int>::value) {
std::cout << "int";
} else {
std::cout << "other";
}
}
九、CRTP 奇异递归模板模式
9.1 基本模式
template<typename Derived>
class Counter {
public:
Counter() { ++count; }
static int count;
};
template<typename D>
int Counter<D>::count = 0;
class My : public Counter<My> {};
9.2 应用场景
- 静态多态
- 防止虚函数调用差怪
- 性能提升
十、实战:构建泛型算法库
10.1 sort_if 功能
template<typename T>
concept LessThanComparable = requires(T a, T b) {
{ a < b } -> std::convertible_to<bool>;
};
template<typename T>
requires LessThanComparable<T>
void sort_if(std::vector<T>& vec) {
std::sort(vec.begin(), vec.end());
}
10.2 高级组合:综合 traits + CRTP + Concepts 构建编译期选择算法
十一、常见问题与解决方案
问题 | 原因 | 解決策略 |
---|---|---|
错误信息复杂 | 模板嵌套 | 分阻类型 + static_assert |
可读性差 | enable_if 突出 | 使用 Concepts |
编译慢 | TMP 递归过深 | 限制递归 |
过度抽象 | CRTP 过深 | 简单化设计 |
十二、结论与学习建议
- 模板技术是环环相扩的
- 前期重培基础,后期重经验
推荐学习步骤
- 熟悉基础函数、类模板语法
- 理解特化、enable_if编译选择
- 精通类型萌取 traits
- 逐步入手 TMP 与 CRTP
- 体验 Concepts 应用
附录
- C++ Templates: The Complete Guide 2nd Edition
- Effective Modern C++ - Scott Meyers
- https://en.cppreference.com