C++模板进阶,模板特化详细讲解

模板进一步介绍

1. 非类型模板参数
这里的模板参数,及出现在参数模板列表的位置

template<class T,size_t n = 10>
class a
{
     
public:
	//[]运算符重载
	 T& operator[](size_t index){
     return _array[index];}
private:
	T _array[n];//定义一个T类型的数组
	//n可以当作常量使用
};

注意:

  • 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  • 非类型的模板参数必须在编译期就能确认结果

2. 模板的特化
之前我们学习模板中,给一个T类型,编译器会自动为我们确定它的类型,这里的特化,及在模板位置给一个数据类型,这样可以防止一些不必要的错误出现。
函数模板的特化步骤:

  • 必须要先有一个基础的函数模板
  • 关键字template后面接一对空的尖括号<>
  • 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  • 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报不同寻常的错误。
template<>
char* is_equal<char*>(char*&a,char*& b)
{
     
	 if(strcmp(left, right) > 0)       
	 	return true;        
	 return false; 
}

3.类模板特化
1.全特化
即模板类型中所有的参数都在参数列表中确定

template<>
class A<int,char>//确定其类型
{
     
public:
  A()
  {
     
    cout<<"A"<<endl;
  }
private:
  int _t1;
  char _t2;
};

2.偏特化
任何针对模版参数进一步进行条件限制设计的特化版本
比如将上述类变为偏特化
部分偏特化

template<class T>
class A<T,char>//将第二个参数类型特化为char第一个为T类型
{
     
public:
  A()
  {
     
    cout<<"A"<<endl;
  }
private:
  T _t1;
  char _t2;
};

进一步限制
偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。比如指针,引用等。

template<class T1,class T2>//两个参数偏特化为指针类型
class A<T1*,T2*>
{
     
public:
  A()
  {
     
    cout<<"A"<<endl;
  }
private:
  T1 _t1;
  T2 _t2;
};

举例

template<class T1,class T2>
class A
{
     
public:
  A()
  {
     
    cout<<"T1 T2"<<endl;
  }
private:
  T1 _t1;
  T2 _t2;
};
//全特化
template<>
class A<int,char>
{
     
public:
  A()
  {
     
    cout<<"A"<<endl;
  }
private:
  int _t1;
  char _t2;
};
//偏特化
template<class T1>
class A<T1,double>
{
     
public:
  A()
  {
     
    cout<<"T1 double"<<endl;
  }
private:
  T1 _t1;
  double _t2;
};
template<class T1,class T2>
class A<T1&,T2&>
{
     
public:
  A()
  {
     
    cout<<"T1& T2&"<<endl;
  }
};
test()
{
     
  A<int&,int&> b;//调用引用的特化版本
  A<int,char> c;//调用全特化版本
  A<int,double> d;//调用偏特化版本
  A<int,int> e;//调用普通版本
}

3 模板分离编译
一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链 接起来形成单一的可执行文件的过程称为分离编译模式。

假如模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义
头文件不参与编译,编译器对源文件进行编译,在源文件中,编译器没有看到具体的函数模板实例化,因此不会生成具体函数,当在main.obj文件中调用了模板函数,但是没有s实例化生成具体代码,因此会发生链接错误。
因此可以:

  • 将声明和定义放到一个文件 “xxx.hpp” 里面或者xxx.h其实也是可以的。推荐使用这种。

总结

优点

  • 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  • 增强了代码的灵活性

缺陷

  • 模板会导致代码膨胀问题,也会导致编译时间变长
  • 出现模板编译错误时,错误信息非常凌乱,不易定位错误

你可能感兴趣的:(C++,c++)