首页 > 编程语言 >一文速通C++全特化/偏特化、重载决议

一文速通C++全特化/偏特化、重载决议

时间:2024-11-12 22:19:54浏览次数:3  
标签:函数 int C++ 泛化 func 特化 模板 速通

全特化/偏特化 重载决议

在开始搞模板元编程、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. 函数模板重载决议 —— 决议出函数主模板:发生在泛化模板(主模板) 之间,会无视模板特化
/*  泛化模板函数 */
// 泛化模板1 (可能被决议后,作为函数主模板)
template<typename T, typename C>
void func(T a, C b){}

// 泛化模板2 (可能被决议后,作为函数主模板)
template<typename T,typename C>
void func(T &a, C &b){}
  1. 决议出函数主模板后:如果函数主模板存在符合的具体化函数模板,才会调用具体化函数模板;
// 根据“惰性实例化”准则
// 只有存在 诸如 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

相关文章

  • 二叉搜索树实现教程:用C++实现数据存储与查找
    文章目录1.二叉搜索树的概念2.二叉搜索树的性能分析3.二叉搜索树的插入4.二叉搜索树的查找5.二叉搜索树的删除6.⼆叉搜索树的实现代码7.⼆叉搜索树key和key/value使⽤场景7.1key搜索场景:7.2key/value搜索场景:7.3key/value⼆叉搜索树代码实现1.二叉搜索树......
  • c++的getline
    getline是C++标准库中的一个函数,用于从输入流中读取一行文本,包括空格和制表符等空白字符,直到遇到换行符为止。它通常用于读取包含空格的字符串。有人会问,为什么不用更好的cin,这是因为getline函数会读取包括空格在内的所有字符,直到遇到换行符为止。而 cin默认会在遇到第一......
  • C++内存泄漏检查工具——Valgrind(--tool = memcheck)
    在写c++程序中通常遇到程序崩溃,我们首先想到的是内存问题如果代码量少看几遍就能看得出来,如果代码量多起来我们就得借助一些工具了比如gdb调试和valgrind中得memcheck来解决内存问题我用的ubuntu,先安装valgrindsudoapt  updatesudoaptinstallvalgrindvalgrind--ve......
  • c++(vector、map、list、deque、set)总结-面试
    目录1.vector2.deque3.list4.map5.set6.queue7.stack8.STL容器使用时机希望在面试和学习过程中可以帮助大家梳理重点C++中有两种类型的容器:顺序容器和关联容器。顺序容器主要有vector、list、deque等。其中vector表示一段连续的内存,基于数组实现,list表示非连续......
  • C++基础 抽象类 类模板 STL库 QT环境
    一、抽象类1、纯虚函数        在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。        语法:virtual返回值类型函数名(参数列表)=0;2.抽象类1)概念        有纯虚函数所在的类,称......
  • C++中的命名空间
    C++命名空间:命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。命名空间用于将代码组织到逻辑组中,还可用于避免名称冲突,尤其是在基本代码包括多个库时。命名空间范围内的所有标识符彼此可见,而没有任何限制。命名空间之外的标识符可通过使用......
  • 【c++】vector
    序列式容器vectorstd::vector 是STL提供的 内存连续的、可变长度 的数组(亦称列表)数据结构。能够提供线性复杂度的插入和删除,以及常数复杂度的随机访问。为什么要使用 vector作为OIer,对程序效率的追求远比对工程级别的稳定性要高得多,而 vector 由于其对内存的动态......
  • 【c++】运算详解
    运算算术运算符运算符功能+ (单目)正- (单目)负* (双目)乘法/除法%取模+ (双目)加法- (双目)减法单目与双目运算符单目运算符(又称一元运算符)指被操作对象只有一个的运算符,而双目运算符(又称二元运算符)的被操作对象有两个。例如 1+2 中加号就是双目运算符,它有 1 和 2 两......
  • 【c++】枚举详解
    简介枚举(英语:Enumerate)是基于已有知识来猜测答案的一种问题求解策略。枚举的思想是不断地猜测,从可能的集合中一一尝试,然后再判断题目的条件是否成立。要点给出解空间建立简洁的数学模型。枚举的时候要想清楚:可能的情况是什么?要枚举哪些要素?减少枚举的空间枚举的范围是......
  • 【c++】结构体和类详解
    结构体结构体(struct),可以看做是一系列称为成员元素的组合体。可以看做是自定义的数据类型。Note本页描述的 struct 不同于C中 struct,在C++中 struct 被扩展为类似 class 的类说明符。定义结构体structObject{intweight;intvalue;}e[array_length];......