全特化/偏特化 重载决议
在开始搞模板元编程、SFINAE、类型萃取、concept 前,我们来回顾一下特化和重载决议。
这堆编译期鬼画符一样的东西,运行期到底会调用哪一个呢?哪怕不会写,你起码需要看得明白不是?
全特化/偏特化
全特化(specialization):具体指明模板类型里全部的类型参数
偏特化(partial specialization)(局部特化):仅指明模板类型里的 几个/一定范围内 的类型参数
-
个数偏特化
<typename X>
存在未指明的类型 -
范围偏特化
-
根据类型的 cv限定符,左右引用,指针 做进一步区分
-
比如int:
const int,int *, const int*,int&,int&&
-
全特化 | 偏特化 | 重载 | |
---|---|---|---|
类模板 | 支持 | 支持 | NA |
函数模板 | 支持 | NA | 支持 |
类模板
优先级:全特化类 > 偏特化类 > 泛化(主版本)模板类
/* 全特化 */
// template<>中为空,代表全特化: 所有类型都在下面特殊化处理
template<>
struct A<int,int,int> { A(){cout<<"全特化 int*3"<<endl;}};
/* 偏特化 */
// 偏特化 - 个数偏特化
template<typename C>
struct A<int,C,int> { A(){cout<<"个数偏特化 int,C,int"<<endl;}};
// 偏特化 - 范围偏特化
template<typename T1,typename T2,typename T3>
struct B<T1*, T2*, T3*> { B(){cout<<"T* 范围偏特化"<<endl;}};
template<typename T1,typename T2,typename T3>
struct B<const T1, const T2, const T3> { B(){cout<<"const T 范围偏特化"<<endl;}};
template<typename T>
struct B<T1&, T2&, T3&> { B(){cout<<"T& 范围偏特化"<<endl;}};
/* 泛化版本 */
template<typename T1,typename T2,typename T3>
struct A { A(){cout<<"泛化"<<endl;} };
函数模板
函数模板仅支持 全特化
优先级:普通函数 > 全特化模板函数 > 泛化模板(主模板)函数
常规函数
/* 常规函数 */
void func(const char* a, const char* b) {}
全特化模板函数
/* 全特化模板函数 */
template<>
void func(int a, double b) {}
重载决议
函数模板的**“惰性实例化”准则**:并不是所有可能的特化都会体现在编译产物中。
- 函数模板重载决议 —— 决议出函数主模板:发生在泛化模板(主模板) 之间,会无视模板特化
/* 泛化模板函数 */
// 泛化模板1 (可能被决议后,作为函数主模板)
template<typename T, typename C>
void func(T a, C b){}
// 泛化模板2 (可能被决议后,作为函数主模板)
template<typename T,typename C>
void func(T &a, C &b){}
- 决议出函数主模板后:如果函数主模板存在符合的具体化函数模板,才会调用具体化函数模板;
// 根据“惰性实例化”准则
// 只有存在 诸如 func('a', 1); 的使用处,编译器才会实例化
// 因此泛化模板1的特化版本(我们就叫它 1-1 吧), 1-1才会存在
template<>
void func(char a, int b){}
// 相对应的,如果没有如下类似的调用
char ch1 = 'a';
int num2 = 1;
func(ch1. num2);
// 泛化2的特化版本 的 特化版本2-1, 可能压根就不存在
template<>
void func(int &a, int &b){}
标签:函数,int,C++,泛化,func,特化,模板,速通
From: https://blog.csdn.net/weixin_41733034/article/details/143698351