C++模板:参数、特化与优化
立即解锁
发布时间: 2025-08-16 01:23:32 阅读量: 2 订阅数: 7 


C++编程语言第四版精华
### C++模板:参数、特化与优化
#### 1. 引言
在过去二十年里,模板从一个相对简单的概念发展成为了大多数高级C++编程的核心。模板对于以下技术至关重要:
- 提高类型安全性(例如,通过消除类型转换的使用);
- 提升程序的抽象级别(例如,使用标准容器和算法);
- 为类型和算法提供更灵活、类型安全且高效的参数化。
这些技术依赖于模板代码以无开销且类型安全的方式使用模板参数的能力,同时也依赖于模板提供的类型推导机制(有时称为编译时多态)。
#### 2. 模板参数和参数类型
模板可以接受以下几种类型的参数:
- **类型参数**:通常使用`typename`或`class`前缀定义,内置类型和用户定义类型都可以作为类型参数。例如:
```cpp
template<typename T>
void f(T);
template<typename T>
class X {
// ...
};
```
- **值参数**:非类型或模板的参数,如整数、指针等。例如:
```cpp
template<typename T, int max>
class Buffer {
T v[max];
public:
Buffer() { }
// ...
};
```
- **模板参数**:可以将模板作为模板参数传递。例如:
```cpp
template<typename T, template<typename> class C>
class Xrefd {
C<T> mems;
C<T*> refs;
// ...
};
```
- **默认模板参数**:可以为模板参数指定默认值,减少重复指定参数的麻烦。例如:
```cpp
template<typename Key, Class V, typename Compare = std::less<Key>>
class map {
public:
explicit map(const Compare& comp ={});
// ...
};
```
以下是不同参数类型的总结表格:
| 参数类型 | 示例 | 说明 |
| ---- | ---- | ---- |
| 类型参数 | `template<typename T>` | 接受任何类型作为参数 |
| 值参数 | `template<typename T, int max>` | 接受常量值作为参数 |
| 模板参数 | `template<typename T, template<typename> class C>` | 接受模板作为参数 |
| 默认模板参数 | `template<typename Key, Class V, typename Compare = std::less<Key>>` | 为参数提供默认值 |
#### 3. 类型作为参数
使用`typename`或`class`前缀定义的模板参数可以接受任何类型。例如:
```cpp
template<typename T>
void f(T);
template<typename T>
class X {
// ...
};
f(1); // T deduced to be int
f<double>(1); // T is double
f<complex<double>>(1); // T is complex<double>
X<double> x1; // T is double
X<complex<double>> x2; // T is complex<double>
```
类型参数没有约束,其有效性仅取决于在模板中的使用,提供了一种“鸭子类型”的形式。用户定义类型和内置类型在作为模板参数时处理方式相同,没有额外的空间或时间开销。
#### 4. 值作为参数
模板值参数可以是以下几种类型:
- 整数常量表达式
- 具有外部链接的对象或函数的指针或引用
- 非重载的成员指针
- 空指针
例如:
```cpp
template<typename T, int max>
class Buffer {
T v[max];
public:
Buffer() { }
// ...
};
Buffer<char,128> cbuf;
Buffer<int,5000> ibuf;
Buffer<Record,8> rbuf;
```
需要注意的是,模板值参数必须是常量,并且不能使用字符串字面量作为模板参数。
#### 5. 操作作为参数
以标准库的`map`为例,如何为键提供比较标准是一个问题。可以通过以下两种方式实现:
- **模板值参数**:传递比较函数的指针。例如:
```cpp
template<typename Key, typename V, bool(*cmp)(const Key&, const Key&)>
class map {
public:
map();
// ...
};
bool insensitive(const string& x, const string& y) {
// compare case insensitive (e.g., "hello" equals "HellO")
}
map<string,int,insensitive> m; // compare using insensitive()
```
- **模板类型参数**:传递比较对象的类型。例如:
```cpp
template<typename Key, Class V, typename Compare = std::less<Key>>
class map {
public:
map() { /* ... */ }
map(Compare c) :cmp{c} { /* ... */ }
// ...
Compare cmp {};
// default comparison
};
map<string,int> m1; // use the default comparison (less<string>)
map<string,int,std::greater<string>> m2; // compare using greater<string>()
```
传递函数对象作为比较操作具有显著优势,如易于内联、无运行时成本等。
以下是两种方式的对比流程图:
```mermaid
graph LR
A[提供比较标准] --> B[模板值参数]
A --> C[模板类型参数]
B --> B1[传递比较函数指针]
C --> C1[传递比较对象类型]
```
#### 6. 模板作为参数
有时将模板作为模板参数传递是有用的。例如:
```cpp
template<typename T, template<typename> class C>
class Xrefd {
C<T> mems;
C<T*> refs;
// ...
};
template<typename T>
using My_vec = vector<T>;
Xre
```
0
0
复制全文
相关推荐









