模板全特化与偏特化

举报
无敌清风蓝 发表于 2023/08/31 22:07:50 2023/08/31
【摘要】 模板全特化与偏特化

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文件中,并且特化版本一般在泛化版本后面即可

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。