模板全特化与偏特化
1.模板全特化与偏特化(局部特化)
原来的模板是,传递进去一个类型模板参数,这个传递的类型可以自己指定,但存在一种情况,传递A类型可以,但传递B类型就报错,我们现在会对B类型这个模板,做单独的设计和代码编写,原来的(通用模板代码和泛化模板代码)不适合这种比较独特的类型,所以引出了模板特化的概念
1.1类模板特化
1.类模板全特化
1)常规全特化
比如一个正常的类模板
template<typename T, typename U>
struct TC
{
TC()
{
cout << "TC泛化版本的构造函数" << endl;
}
void func()
{
cout << "TC泛化版本" << endl;
}
};
全特化就是把所有的类型模板参数(这里是T,U)全部用具体的类型替代
template<> //全特化,则这里不写了,因为都用具体的类型表示了
struct TC<int, int>
{
TC()
{
cout << "TC<int, int>特化版本的构造函数" << endl;
}
void func()
{
cout << "TC<int, int>特化版本" << endl;
}
};
在main主函数调用的时候,只有使用了TC模板,并且指定了int,int类型,编译器就会自动执行这些特化版本的代码
TC<char, char> tchar; //TC泛化版本的构造函数
tcchar.functest(); //Tc泛化版本
TC<int, int> tcint; //TC<int, int>特化版本的构造函数
tcint.functest(); //TC<int, int>特化版本
2)特化类模板的成员函数
template<> //全特化,则这里不写了,因为都用具体的类型表示了
void TC<double , int>::func()
{
cout << "TC<int, int>的func()特化版本" << endl;
}
在main里面
TC<double, int> tcdi; //TC泛化版本构造函数
tcdi.func(); //TC<int, int>的func()特化版本
因为并没有为double int特化TC类模板(特化的只有int, int),所以构造tcdi调用的是泛化版本的TC类模板的构造函数,但是专门为成员函数func进行了一个double int特化,所以调用func函数执行的是特化版本的
1.2.类模板的偏特化(局部特化)
两个方面来说,一个是模板参数数量的偏特化,一个是模板参数范围上的偏特化
1)模板参数数量的偏特化
比如只特化两个,一个保留
template<typename T, typename U, typename W>
struct TCP
{
TCP()
{
cout << "TCP泛化版本构造函数" << endl;
}
void functest()
{
cout << "TCP泛化版本" << endl;
}
};
下面看看特化
template<typename U> //因为特化两个,那不特化的就留下来
struct TCP<int, U, double>
{
TCP()
{
cout << "TCP<int, U, double>偏特化版本构造函数" << endl;
}
void functest()
{
cout << "TCP<int, U, double>偏特化版本" << endl;
}
};
在main中
TCP<double, int, double> tcpdi; //TCP泛化版本构造函数
tcpdi.functest(); //TCP泛化版本
TCP<int, int, double> tcpdi //TCP<int, U, double>偏特化版本构造函数
tcpdi.functest()l //TCP<int, U, double>偏特化版本
2)模板参数范围上的偏特化
参数范围的理解,比如int变成const int;T变为T*,T&(左值引用),T&&(右值引用),针对T来说,范围都变小了
这里就举一个例子
记住有特化的前提是必须有泛化
template<typename T>
struct TCF
{
TCF
{
cout << "TCF泛化版本构造函数" << endl;
}
void func()
{
cout << "TCF泛化版本" << endl;
}
}
写一个模板参数范围上的偏特化
template<typename T>
struct TCF<const T>
{
TCF
{
cout << "TCF<const T>特化版本构造函数" << endl;
}
void func()
{
cout << "TCF<const T>特化版本" << endl;
}
}
在main里面
TCF<double> td; //TCF泛化版本构造函数
td.func(); //TCF泛化版本
TCF<const int> tcfi; //TCF<const T>特化版本构造函数
tcfi.func(); //TCF<const T>特化版本
2函数模板特化
2.1.函数模板全特化
泛化
template<typename T, typename U>
void tfunc(T& tmprv, U& tmprv2)
{
cout << "tfunc泛化版本" << endl;
cout << tmprv << endl;
cout << tmprv2 << endl;
}
在main函数中
const char* p = "China";
int i = 12;
tfunc(p , i);
结果是
tfunc泛化版本
China
12
T这里代表的是const char*
tmprv是const char* &类型
现在写一个全特化
template<>
void tfunc(int& tmprv, double& tmprv2)
& tmprv2)
{
cout << "tfunc<int, double特化版本" << endl;
cout << tmprv << endl;
cout << tmprv2 << endl;
}
在main函数中
int k = 12;
double db = 15.8f;
tfunc(k, db);
结果是
tfunc<int, double特化版本
12
15.8
全特化实际上等价于实例化一个函数模板,并不等价于一个函数重载
如果这时候有一个也是int,double的函数重载,那在运行tfunc(k, db);,则会调用函数重载,而不是特化
2.函数模板偏特化
函数模板不能偏特化,只有类模板才能偏特化
3.模板特化版本放置位置建议
模板定义和实现一般都放在.h文件中
所以模板的特化版本应该和模板泛化版本都放在同一个.h文件中,并且特化版本一般在泛化版本后面即可
- 点赞
- 收藏
- 关注作者
评论(0)