【c++】 模板进阶


前言

模板参数分类类型形参与非类型形参。 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

一、模板参数

非类型模板参数的引用,解决了我们部分问题,

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果。
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文件当中。因为这样子在编译的时候他的函数的地址就已经确认了。


总结

模板进阶就到这里!!

猜你喜欢

转载自blog.csdn.net/weixin_52344401/article/details/121651105