1.非类型模板参数
类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
非类型形参:用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
2.类模板的特化
一般情况下,模板可以实现一些与类型无关的代码,但是对于一些特殊的可能会得到一些错误的结果。此时,就需要对模板进行特化。在原模版的基础上,针对特殊类型及逆行特殊化的实现方式。模板特化分为函数模板特化与类模板特化。
2.1函数模板特化
1.必须现有一个基础的函数模板
2.关键字template后面接有一对空的尖括号<>
3.函数名后跟一对尖括号,尖括号中指定需要特化的类型
4.函数形参标:必须要和模板函数的基础参数类型完全相同,如果不同编译器会报奇怪的错误。
// 函数模板 -- 参数匹配
template<class T>
bool Less(T left, T right)
{
return left < right;
}
// 对Less函数模板进行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{
return *left < *right;
}
int main()
{
cout << Less(1, 2) << endl;
Date d1(2022, 7, 7);
Date d2(2022, 7, 8);
cout << Less(d1, d2) << endl;
Date* p1 = &d1;
Date* p2 = &d2;
cout << Less(p1, p2) << endl; // 调用特化之后的版本,而不走模板生成了
return 0;
}
bool Less(Date* left, Date* right)
{
return *left < *right;
}
2.2类模板特化
全特化:将模板参数列表中所有的承诺书都确定化
偏特化:部分特化;参数更进一步的限制。不仅仅是特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
#include<vector>
#include<algorithm>
template<class T>
struct less
{
bool operator()(const T& x, const T& y)const//这是less结构体的一个成员函数,//重载了函数条用操作符operator()。它允许less对象像函数一样被调用。//函数参数使用常量引用可以避免复制开销,并确保函数不会修改传入的对象。
{
return x < y;
}
};
int main()
{
Date d1(2022,7,7);
Date d2(2022,7,6);
Date d3(2022,7,8);
vector<Date> v1;
v1.push_back(d1);
v1.push_back(d2);
v1.push_back(d3);
sort(v1.begin(),v1.end(),less<Date>());//首先规定范围,最后一个是排序的比较函数对象,//使用less类模板的实例来比较Date对象。就可以实现将Date对象日期按照从早到晚进行排序。
vector<Date*> v2;
v2.push_back(&d1);
v2.push_back(&d2);
v2.push_back(&d3);
// 可以直接排序,结果错误日期还不是升序,而v2中放的地址是升序
// 此处需要在排序过程中,让sort比较v2中存放地址指向的日期对象
// 但是走Less模板,sort在排序时实际比较的是v2中指针的地址,因此无法达到预期
sort(v2.begin(), v2.end(), Less<Date*>());
//因此,就需要对less类模板按照指针方式特化
template<>
struct less<Date*>
{
bool operator()(Date* x,Date* y)const
{
return *x < *y;
}
};
3.模板总结
优点:模板复用了代码,节省资源,更快的迭代开发,c++的标准模板库(STL)因此而产生
增强了代码的灵活性
缺点:
1. 模板会导致代码膨胀问题,也会导致编译时间变长2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误
4.改错
1、下列的模板声明中,其中几个是正确的( )
1)template
2)template<T1,T2>
3)template<class T1,T2>
4)template<class T1,class T2> 对
5)template<typename T1,T2>
6)template<typename T1,typename T2> 对
7)template<class T1,typename T2> 对
8)<typename T1,class T2>
9)template<typeaname T1, typename T2, size_t N> 对
10)template<typeaname T, size_t N=100, class _A=alloc<T>> 对
11)template<size_t N> 对
2、
3、
A.模板不支持分离编译,所以不能在.h声明,在.cpp实现
B.由于不支持分离编译,模板程序一般只能放在一个文件里实现
C.不支持分离编译并不是语法错误,而是暂时的编译器不支持,不久将来,或许会被支持
D.模板程序被编译两次,这是不能分离编译的原因所在