【C++】第十四节—模版进阶(非类型模版参数+模板的特化+模版分离编译+模版总结)
你好,我是云边有个稻草人

目录
【了解array 容器—array和普通数组的区别在哪里?—对越界的检查】
正文开始——
一、非类型模板参数
模板参数分为类型形参与非类型形参。
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
注意:浮点数、类对象以及字符串是不允许作为非类型模板参数的。非类型的模板参数必须在编译期就能确认结果。类型模版参数和非类型模版参数都可以用缺省值,但是非类型模版参数是有限制的,只能用整型类型,浮点型,类类型等都是不可以的!
【非类型模版参数的用处在哪里? 】

#include<iostream> using namespace std; //#define N 10//宏定义 //只支持整型 template<class T,size_t N = 10>//非类型模版参数可以给缺省值 class Stack { private: T _a[N]; int _top; }; ////C++20以后才支持浮点数 //template<class T, double N = 10.1>//非类型模版参数可以给缺省值 //class Array //{ //private: //}; int main() { Stack<int,20> st1; Stack<int,200> st2; Stack<int> st3; return 0; }【了解array 容器—array和普通数组的区别在哪里?—对越界的检查】

二、模板的特化(特殊化处理)
2.1 概念
通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理。
比如:实现了一个专门用来进行小于比较的函数模板
class Date { public: Date(int year = 2025, int month = 7, int day = 9) :_year(year) , _month(month) , _day(day) { } bool operator<(const Date& d)const { return (_year < d._year) || (_year == d._year && _month < d._month) || ((_year == d._year && _month == d._month && _day == d._day)); } private: int _year; int _month; int _day; }; //函数模版 template<class T> bool Less(T left,T right) { return left < right; } int main() { Date d1(2025, 7, 9); Date d2(2025, 9, 9); Date* p1 = new Date(2025, 8, 9); Date* p2 = new Date(2025, 10, 9); cout << Less(1, 2) << endl;//可以判断,结果正确 cout << Less(d1, d2) << endl;//可以判断,结果正确 cout << Less(p1, p2) << endl;//结果随机。其实这里是对new出来的地址进行比较,当然是随机,那怎么办?—特化! return 0; }可以看到,Less绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果。上述示例中,p1指向的d1显然小于p2指向的d2对象,但是Less内部并没有比较p1和p2指向的对象内容,而比较的是p1和p2指针的地址,这就无法达到预期而错误。 此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特化中分为函数模板特化与类模板特化。
2.2 函数模版特化
函数模板的特化步骤: