目录
[1. 非类型模板参数](#1. 非类型模板参数)
[2. 类模板的特化](#2. 类模板的特化)
[2.1 函数模板特化](#2.1 函数模板特化)
[2.2 类模版特化](#2.2 类模版特化)
[3. 模板的分离编译](#3. 模板的分离编译)
**1.**非类型模板参数
模版参数有两种,一种叫类型模版参数,一种叫做非类型模版参数。今天我们来讲讲非类型模版参数。
template <int N> 中的 int N 就是典型的非类型模板参数。这里的 int 是参数的类型,而 N 是参数名,它接收的是一个具体的常量值 ,而非像普通类型模板参数(如 template <typename T>)那样接收一个 "类型"。
两者核心区别就是:
- 类型模板参数:传递 "类型"(如
T = int) - 非类型模板参数:传递 "常量值"(如
N = 10)
简单来说就是类型模版参数是改变类型,非类型模版参数改变的是类型后面的数。
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
2. 非类型的模板参数必须在编译期就能确认结果。
cpp
// 模板参数 <int N> 就是非类型参数(传递的是"值")
template <int N> // N 是一个编译期已知的整数
class FixedArray {
private:
int arr[N]; // 用 N 作为数组长度(编译时就确定了)
public:
// 打印数组长度
void printSize() {
std::cout << "数组长度是:" << N << std::endl;
}
};
int main() {
// 实例化时指定具体的"值"(非类型参数)
FixedArray<3> arr3; // N=3,创建一个长度为3的数组
FixedArray<5> arr5; // N=5,创建一个长度为5的数组
arr3.printSize(); // 输出:数组长度是:3
arr5.printSize(); // 输出:数组长度是:5
return 0;
}
**2.**类模板的特化
2.1 函数模板特化
模板的特化(Template Specialization)是 C++ 中为模板提供 "特殊处理" 的机制。简单说就是:当模板的参数满足某种特定条件时,我们可以为它定义一套专门的实现,而不使用通用模板的代码。
比如说下面这个代码,第一个Print就是普通的模版,第二个Print就是特化的模版。我们要在函数的名字后面加上<char>说明我们要特殊处理的是char类型的。由于计算机是从上往下编译的,所以当它在mian函数里面遇到Print,同时里面是char类型的时候,它会自动匹配第二个,然后打印出对应的ASCII码。
cpp
#include <iostream>
// 通用模板(适用于大多数类型)
template <typename T>
void Print(T value) {
std::cout << "通用模板:" << value << std::endl;
}
// 对 char 类型的特化版本
template <> // 特化标记:空参数列表,表示"针对特定类型"
void Print<char>(char value) { // 明确指定特化的类型:char
std::cout << "char 特化:字符 '" << value << "' 的 ASCII 码是 " << (int)value << std::endl;
}
int main() {
Print(123); // 匹配通用模板,输出:通用模板:123
Print('A'); // 匹配 char 特化版本,输出:char 特化:字符 'A' 的 ASCII 码是 65
return 0;
}
2.2 类模版特化
下面这个就是类模版特化中的全特化,简单来说就是给类的每一个参数都传递模版参数,就叫做全特化。
PS:如果只给一个类的部分参数传递模版参数那就是偏特化。
cpp
#include <iostream>
#include <string>
// 通用类模板:处理任意类型的数据
template <typename T>
class DataProcessor {
public:
void process(T data) {
std::cout << "通用处理:" << data << "(类型未知,按默认方式处理)" << std::endl;
}
};
// 全特化:专门处理 int 类型
template <> // 全特化标记(空参数列表)
class DataProcessor<int> { // 明确指定特化的类型是 int
public:
void process(int data) {
std::cout << "int 专用处理:" << data << "(整数翻倍后为 " << data * 2 << ")" << std::endl;
}
};
// 全特化:专门处理 string 类型
template <>
class DataProcessor<std::string> { // 明确指定特化的类型是 string
public:
void process(std::string data) {
std::cout << "string 专用处理:" << data << "(字符串长度为 " << data.size() << ")" << std::endl;
}
};
int main() {
// 测试通用模板(处理 double 类型,没有特化版本)
DataProcessor<double> dProc;
dProc.process(3.14); // 用通用模板处理
// 测试 int 特化版本
DataProcessor<int> iProc;
iProc.process(10); // 用 int 专用处理
// 测试 string 特化版本
DataProcessor<std::string> sProc;
sProc.process("hello"); // 用 string 专用处理
return 0;
}
**3.**模板的分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链 接起来形成单一的可执行文件的过程称为分离编译模式,比如说我写的那个boost搜索引擎项目就是分离编译模式。
这个就相当于写了一个通用的类,然后我们想用时对他进行调用。
