前言
模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。一、模板参数
非类型模板参数的引用,解决了我们部分问题,
- 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
- 非类型的模板参数必须在编译期就能确认结果。
namespace ljh
{
// 定义一个模板类型的静态数组
template<class T =int, size_t N = 10>
class array
{
private:
T _array[N];
size_t _size;
}
}
int main()
{
ljh::array<int,100> s1;
ljh::array<int,70> s2;
}
类似上面这种情况,我们两个栈需要开辟不同的空间的时候,如果没有这个模板参数的话我们就需要写两个类。
若是全缺省的类,我们调用也需要 ljh::array<> s1;
模板的特化
什么时候需要用到呢?
当我们实现一个Is_empty的函数用来判断两个值是否相同。但是由于不同类型可能比较方式有所差异,我们这个时候可以使用特化,或者利用模板的匹配原则。
template<class T>
bool Is_empty(T left,T right)
{
cout << "hah" << endl;
return left == right;
}
template<>//特化
bool Is_empty<char*>(char* left,char* right)
{
return strcmp(left,right) == 0;
}
//模板的匹配原则
bool Is_empty(char* left,char* right)
{
return strcmp(left,right) == 0;
}
int main()
{
int left = 0;
int right = 0;
//cout << Is_empty(left, right)<<endl;
char str1[] = "woaini";
char str2[] = "woaini";
cout<<typeid(str1).name()<<endl;
cout << Is_empty(str1, str2) << endl;
return 0;
}
注意这里的str1,str2本质是数组名,在传参的时候,存在类型转换,所以我们要在上面的传参过程中如果讲模板函数改成下面的const T&,则对于特化版本会存在问题。
template<class T>
bool Is_empty(const T& left,const T& right)//error!
{
cout << "hah" << endl;
return left == right;
}
template<>
bool Is_empty<char*>(char* left,char* right)
{
return strcmp(left,right) == 0;
}
二、分离编译
1.引入库
解决方案1:显式指定实例化。
解决方案2:不分离编译。声明和定义在一个.h文件当中。因为这样子在编译的时候他的函数的地址就已经确认了。
总结
模板进阶就到这里!!