一、名词区分(避免混淆)
类模板: 重点是模板,表示的是一个模板,专门用于产生类的模子。
模板类: 重点是类,表示的是由一个模板生成而来的类。
函数模板: 重点是模板,表示的是一个模板,专门用来生产函数。
模板函数: 重点是函数,表示的是由一个模板生成而来的函数。
类型模板参数: 模板的参数,如int、double等
非类型模板参数: 模板的参数,如1、2、3等
参考资料: 模板类与类模板、函数模板与模板函数等的区别
二、类模板的几种用法
2.1、基础类模板
// 类模板
template<class T1, class T2>
class MyExample {
public:
bool equal(T1 a, T1 b);
private:
T2 data;
};
template<class T1, class T2>
bool MyExample<T1, T2>::equal(T1 a, T1 b) {
return a == b;
}
// 实例化
MyExample<int, double> a;
2.2、类模板的全特化
即指定类模板所有参数的具体类型。通过模板全特化,可以针对特定参数类型,对类声明的内容进行定制。全特化的模板参数列表是空的。
template<>
class MyExample<float, int> {
public:
bool equal(float a, float b);
private:
int data;
};
bool MyExample<float, int>::equal(float a, float b) {
std::cout << "全特化" << std::endl;
return std::abs(a - b) < 10e-3;
}
// 实例化
MyExample<float, int> a;
2.3、类模板偏特化
即指定类模板部分参数的具体类型。还需要给出剩余的"模板形参"和必要的"模板实参"。
template<class T>
class MyExample<float, T> {
public:
bool equal(float a, float b);
private:
T data;
};
template<class T>
bool MyExample<float, T>::equal(float a, float b) {
std::cout << "偏特化" << std::endl;
return std::abs(a - b) < 10e-3;
}
// 实例化
MyExample<float, double> a;
2.4、成员函数模板:函数模板作为类模板成员
template<class T1, class T2>
class MyExample2 {
public:
bool equal(T1 a, T1 b);
template<typename T3>
void func1(T3 arg) {
std::cout << arg << std::endl;
}
private:
T2 data;
};
template<class T1, class T2>
bool MyExample2<T1, T2>::equal(T1 a, T1 b) {
return a == b;
}
// 实例化
MyExample2<int, double> b;
2.5、类模板的类型模板参数携带默认类型
在实例化类模板时可以不再声明模板参数类型,但是尖括号是必要的。
template<class T1 = int, class T2 = double>
class MyExample3 {
public:
bool equal(T1 a, T1 b);
private:
T2 data;
};
template<class T1, class T2>
bool MyExample3<T1, T2>::equal(T1 a, T1 b) {
return a == b;
}
// 实例化
MyExample3<> c;
MyExample3<int, double> d;
2.6、类模板的非类型模板参数携带默认值
template<class T1, class T2, std::uint32_t num = 5>
class MyExample4 {
public:
bool equal(T1 a, T1 b);
private:
T2 values[num];
};
template<class T1, class T2, std::uint32_t num>
bool MyExample4<T1, T2, num>::equal(T1 a, T1 b) {
return a == b;
}
// 实例化
MyExample4<int, double, 6> e;
三、函数模板的几种用法
- 函数模板只能全特化
- 模板函数不支持默认模板参数
- 函数模板调用时,可以不指定类型模板参数,因为编译器会根据实参进行推导
3.1、普调函数模板
template<typename T1>
bool equal(T1 a, T1 b) {
return a == b;
}
3.2、函数模板全特化
template<>
bool equal(double a, double b) {
return std::abs(a - b) < 10e-3;
}