函数模板与类模板关于特化的不同

392 阅读2分钟

一、类模板的全特化与偏特化:

  • 均要求有一个主模板类(里面全是未知Type参数的正常模板类)
  • 全特化是把主模板中所有未知类型变为确定类型
  • 偏特化的第一种形式:保留一部分未知类型,确定一部分类型;
  • 偏特化的第二种形式:限定传入类型的范围
  • 把template<typename T1,typename T2>里的东西搬到class<T1*,T2*>里面去限定

template <class T1,class T2>
class Test
{

};
//主模板

template <>
class Test<int,double>
{

}
//全特化


template <class T1,class T2>
class Test
{

};
//主模版
template < class T>
class Test < T,int >
{

};
//偏特化1


template <class T1,class T2>
class Test
{

};
//主模版
template <class T1,class T2>
class Test <const T1*,const T2*>
{

};
//偏特化2


二、函数模板的全特化

  • 函数模板没有偏特化。所谓的“函数偏特化”其实是名字相同的两个不一样的函数模板。
  • 函数模板允许参数列表中的某些参数类型使用模板,某些确定。就如同类允许某些变量、返回值使用模板,某些变量确定一样。
  • 函数模板全特化时,如果主模板的参数列表做了限定,全特化模板必须与其保持一致的形式。

template<class T,class Y> bool Isequal(const T& p1, const Y& p2)
{ return p1 == p2; }
//函数主模板,且对参数进行了范围限定

template<> bool Isequal<int,double>(const int& p1, const double& p2)
{ return p1 == p2; }
//全特化,注意括号里两个形参类型必须对应特化完的两个具体类型,且范围限定也要一致

template bool Isequal(X p1, string p2){ return p1 == p2; }
//注意,这不是偏特化!特化的前提条件:函数名之后要有<>才是特化。故这是同名的另一模板,把原模板去掉并不影响编译,不使用X也不影响编译;

/*template bool Isequal<S,double>(S p1, double p2){ return p1 == p2; } */
//此处"偏特化"编译不通过:

image.png

三.调用顺序

当给定语句与多个函数匹配时,调用顺序:
形参完全匹配的非模板函数>形参完全匹配的全特化函数模板>未特化的函数模板

using namespace std;

template <class T1,class T2>  
void test(T1 a,T2 b)
{
    cout<<"主模板"; 
}

template <>  
void test<int,double>(int a,double b)
{
    cout<<"全特化"; 
}

void test(int a,double b)
{
    cout<<"不是模板"; 
}

int main()
{
	test(5,4.9999);
}

image.png