2025-01-10 22:29:51 +08:00
|
|
|
|
# 模板
|
|
|
|
|
|
2025-04-04 17:35:35 +08:00
|
|
|
|
## 目录
|
|
|
|
|
- [函数模板](#)
|
|
|
|
|
- [生成](#)
|
|
|
|
|
- [类模板](#)
|
|
|
|
|
- [完美转发](#)
|
|
|
|
|
- [可变参数](#可变参数)
|
2025-01-10 22:29:51 +08:00
|
|
|
|
|
2025-04-04 17:35:35 +08:00
|
|
|
|
## 函数模板
|
2025-01-10 22:29:51 +08:00
|
|
|
|
```cpp
|
|
|
|
|
template <typename T>
|
2025-04-04 17:35:35 +08:00
|
|
|
|
void swap(T &a, T &b);
|
2025-01-10 22:29:51 +08:00
|
|
|
|
```
|
2025-04-04 17:35:35 +08:00
|
|
|
|
__函数模板必须放在编译器可见的地方里,因为不是函数实体,只能算编译指令__
|
2025-01-10 22:29:51 +08:00
|
|
|
|
|
2025-04-04 17:35:35 +08:00
|
|
|
|
### 生成
|
|
|
|
|
**隐式实例化**
|
2025-01-10 22:29:51 +08:00
|
|
|
|
```cpp
|
|
|
|
|
int a=0, b=3;
|
|
|
|
|
swap<int>(a, b);
|
|
|
|
|
```
|
2025-04-04 17:35:35 +08:00
|
|
|
|
**显式实例化**
|
2025-01-10 22:29:51 +08:00
|
|
|
|
```cpp
|
|
|
|
|
template void swap<int>(int&, int&); // 使用模板生成int类型的函数定义
|
|
|
|
|
```
|
2025-04-04 17:35:35 +08:00
|
|
|
|
**显式具体化** 这个可以放到其他文件里,因为是有实体的
|
2025-01-10 22:29:51 +08:00
|
|
|
|
```cpp
|
|
|
|
|
template <> void swap<int>(int&, int&);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 类型推导
|
|
|
|
|
+ decltype()
|
|
|
|
|
```cpp
|
|
|
|
|
int a;
|
|
|
|
|
decltype(a) var;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 类模板
|
2025-04-04 17:35:35 +08:00
|
|
|
|
同样没有实体,包括类成员方法等都要写成模板的格式
|
2025-01-10 22:29:51 +08:00
|
|
|
|
|
2025-04-04 17:35:35 +08:00
|
|
|
|
## 完美转发
|
|
|
|
|
- [右值引用](./class.md#):有关完美转发的基础
|
|
|
|
|
完美转发允许模板函数将参数原封不动地转发给另一个函数,保留其左值或右值的性质。这在编写通用代码时非常有用,例如模板库或函数包装器
|
|
|
|
|
|
|
|
|
|
完美转发的核心是std::forward,它根据模板参数T的类型(左值引用或右值引用)来决定如何转发参数
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
template <typename T>
|
|
|
|
|
void wrapper(T&& arg) {
|
|
|
|
|
// 转发 arg 到另一个函数,保留其左值或右值性质
|
|
|
|
|
targetFunction(std::forward<T>(arg));
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 可变参数
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
void print() {} // 终止递归
|
|
|
|
|
template <typename T, typename... Types)
|
|
|
|
|
void print(const T& firstArg, const Types&... args) {
|
|
|
|
|
std::cout << firstArg << std::endl;
|
|
|
|
|
print(args...);
|
|
|
|
|
}
|
|
|
|
|
```
|