typename 和 class 的唯一区别
在类模板中使用嵌套类型时,前面需要加上 typename 或在类型形参声明时使用 typename。这是因为编译器无法确定 T::NestedType 是静态成员变量还是类型,需要使用 typename 显式指明。
非类型模板参数
模板参数分为类型形参与非类型形参。类型形参出现在模板参数列表中,跟在 class 或 typename 之后。非类型形参则是使用常量作为类或函数模板的参数,在模板内部可将其视为常量使用。
非类型形参的要求:
- 必须是整型形参(如
size_t和int)。 - 必须是常量(编译期间能确定),传参时必须直接传常数,模板内部不能对其修改。
模板的特化
概念:在原模板类的基础上,针对特殊类型进行特殊化的实现方式。模板特化分为函数模板特化与类模板特化。注意:必须要有主模板之后才能对模板进行特化。
函数模板的特化
函数模板特化最好用重载方式替代。特化后的函数形参表必须与模板函数的基础参数类型完全相同,否则编译器可能报错。函数模板不支持偏特化。
template<class T> bool Less(T left, T right) { return left < right; }
// 函数模板的特化写法
template<> bool Less<int*>(int* left, int* right) { return *left < *right; }
通常建议使用函数重载替代函数模板特化:
bool Less(int* left, int* right) { return *left < *right; }
若使用泛型指针版本:
template<class T> bool Less(T* left, T* right) { return *left < *right; }
此时传入 int*,则 T 为 int。
类模板的特化
类模板的特化分为全特化和偏特化。


