1_2.从案例中理解什么是模板特化1_2
1.1、本课程内容是用来干嘛的
(1)3.2主要讲了顺序容器,3.3讲了泛型算法,都是使用STL所必须掌握的
(2)本课程讲的特化和萃取,是STL内部实现所需要的,属于深度技术
(3)下个课程3.5会继续讲剩余的其他容器
(4)普通函数的优先级比特化函数高。错
优先级一样,但是在普通函数放在特化函数后面时,会函数重载,所以会执行普通函数。特化函数放在后面时,会将普通函数重载掉,就会执行特化函数。
1.2、通过一个案例理解模板特化
(1)案例前奏:写一个add函数库,可以适用于各种数据类型。结论是模板比函数重载好用。
(2)案例:写一个GreaterThan函数,可以对比各种数据类型的大小。
(3)特殊要求:int等比较数值大小,但string类型对比时,不比较字典序,而是以字符串长短来比较
1.3、模板特化总结
(1)模板特化有点类似于函数重载,而且都是编译链接时确定,而非运行时确定的。
(2)特化,specialize,就是让模板参数T在某个具体类型时可以特殊化指定处理
(3)特化的模板声明,前面一般是template<>
3.偏特化和全特化
3.1、全特化与偏特化概念
(1)全特化,特化原模板的所有模板类型为具体类型
(2)偏特化,又叫局部特化,特化原模板的部分类型,或部分特化原模板的类型
(3)全特化比较简单,本节即可全部解决。而偏特化更复杂,是之后讨论的重点。
3.1、函数模板的全特化
(1)代码实践,单个模板参数
(2)代码实践,多个模板参数
3.2、类模板的全特化
(1)代码实践,单个模板参数
(2)代码实践,多个模板参数
4_5.类模板的多种偏特化1_2
4.1、类模板的第一种偏特化
(1)特化多个模板参数中的一部分参数
(2)这种比较简单,代码实践演示
4.2、类模板的第二种偏特化
(1)特化为T的指针类型
(2)这种特化理解起来稍微有点绕,实战演示
4.3、类模板的第三种偏特化
(1)特化为T的其他类模板,譬如vector
(2)这种特化理解起来难度更大,实战演示
4.4、类模板的第4种偏特化
(1)特华为带const的版本
6.函数模板为什么不能偏特化
6.1、事实
(1)代码演示,函数模板确实不支持偏特化,只能全特化,这是编译器决定的
(2)怎么办?用模板函数重载即可
(3)总结:为什么函数模板不能偏特化?因为没必要支持,模板函数重载就能搞定
6.2、分析深度原因
(1)C++语言设计基本原则:后出现的语法尽量兼容且不破坏原有的语法规则
(2)C++一开始就支持函数重载,所以模板函数自然沿用了支持函数重载
(3)偏特化实现的效果,完全可以用模板函数重载实现,所以没必要让模板函数可以偏特化
(4)再思考:类模板为什么可以偏特化?因为类不能重载
7.编译器匹配规则和特化的总结
7.1、编译器匹配规则
(1)第1步先匹配非模版函数,也就是普通函数,如果匹配到就执行,错误
(2)第2步再匹配基础泛化版函数,如果匹配不到就报错了,匹配到进入下一步
(3)第3步再匹配完全特化版本,如果匹配到就执行,匹配不到就执行上一步匹配到的泛化版本
(4)一个小细节:函数模板的特化(当然是全特化)不参与函数重载
7.2、特化与递归结合
(1)特化与递归结合,可以很巧妙的实现编译期的条件判断
(2)详见:https://blog.csdn.net/liuxuejiang158blog/article/details/17678573
7.3、特化的最后总结
(1)特化本质上是我们顶替了编译器的工作,我们帮编译器做了类型推导
(2)模板特化和模板实例化这2个概念的对比
(3)全特化本质上是一个实例,而偏特化本质上还是一个模板,只是原来模板的一个子集,所以全特化的函数模板,本质上是实例(但不参与普通函数的重载),从而不会与函数模板产生二义性
8.类型萃取的目的和意义
8.1、类型萃取的用途
(1)典型应用就是:在模板函数中区分T是源生类型POD还是自定义类型
(2)POD,Plain Old Data,简单理解就是C++从C继承而来的基本类型,如int、double等
(3)POD类型的本质是没有C++叠加的那些高级特征(构造析构,拷贝构造,移动语义,虚函数等)
8.2、为什么要区分POD类型和非POD类型
(1)典型案例就是copy时,POD类型直接memcpy即可,而非POD类型需要用for循环加=挨个对象拷贝
(2)非POD类型不能memcpy,本质是因为需要深拷贝以避免出错
(3)代码演练:int数组和string数组的复制对比
array<string,3> s1={
"qwer","linux","os"};
array<string,3> s2;
transform(s1.begin(), s1.end(), s2.begin(),[](string c) -> string {
return c;});
for(string sx:s2)
cout << sx << " ";
cout <<endl;
9.类型萃取实战演练
9.1、使用is_pod解决上节中的问题
(1)std::is_pod介绍
(2)代码实战,使用is_pod来完善mycopy解决上节中的问题
9.2、std提供的其他类型萃取
10.类型萃取是如何实现的
10.1、一种可能的实现
(1)把所有pod类型组成列表,在内部挨个判断
(2)优点:可以实现,且能实现<type_traits>中所有的标准库萃取工具
(3)缺点:运行时判断,占用运行时资源,效率低
10.2、使用类模板的特化实现
(1)代码实践演示
(2)总结:特化实现萃取的关键,就是特化版本的优先级高于泛化版本
(3)思考:使用类模板特化,是否会增加代码量,影响程序效率?
11.类型萃取的另一种可能实现
11.1、不使用静态成员变量
11.2、改为使用成员函数
11.3、使用typedef增加一层中间层
(1)class/struct内使用typedef定义子类型的方法
(2)增加名为value_type的子类型中间层,实现pod判断
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
#if 0
struct TrueType
{
bool GetType()
{
return true;
}
};
struct FalseType
{
bool GetType()
{
return false;
}
};
// 泛化版本的my_is_pod
template<typename T> struct my_is_pod
{
typedef FalseType value_type;
};
// int类型的特化版本
template<> struct my_is_pod<int>
{
typedef TrueType value_type;
};
int main(void)
{
cout << boolalpha << my_is_pod<int>::value_type().GetType() << endl
return 0;
}
#elseif
template<typename T> struct my_is_pod
{
bool value;
my_is_pod()
{
value = false;
}
};
template<> struct my_is_pod<int>
{
bool value;
my_is_pod()
{
value = true;
}
};
int main(void)
{
//my_is_pod<int>()相当于是构建了一个临时对象
cout << boolalpha << my_is_pod<int>().value << endl
return 0;
}
#endif
12.迭代器萃取与泛型算法
12.1、STL的核心
(1)STL,就是C++提供的一套标准实现的template化的library
(2)STL有很多内容,但是核心就是2个:泛型容器、泛型算法
(3)为了实现泛型容器,引入了迭代器,迭代器是指针的泛化抽象
(4)泛型算法可以接受多种容器,每种容器内可以存储多种数据载体,这就是泛型算法的2级泛化支持
12.2、泛型算法实现的难题和解法
(1)问题1:泛型算法无法预知自己处理的是什么容器
(2)解决思路:将容器降级为迭代器来对接泛型算法。所以任何容器都必须内置一个迭代器
(3)问题2:泛型算法无法预知容器内存储的元素类型,是否POD
(4)解决思路:提供迭代器萃取器,在泛型算法内预先萃取并使用容器元素类型
13.迭代器萃取器的设计解读
(1)迭代器萃取器本质是一个类,叫iterator_traits,属于辅助迭代器的第三方类
(2)解读参考:https://blog.csdn.net/virtual_func/article/details/48398451
14.迭代器萃取器的特化
14.1、萃取器的特化讲解
(1)参考:https://blog.csdn.net/terence1212/article/details/52287762
(2)总结:本质是偏特化结合类型萃取技术
14.2、本课程总结
(1)本课程主要讲了2项技术,一个是特化,一个是萃取
(2)特化的核心价值是,让模板类/函数按一定优先级规则去匹配
(3)萃取的核心价值是,让我们在写泛型算法时可以预先得知未来传参容器及容器内元素的型别特征
(4)如果只是使用STL,实际上不需要关注特化和萃取
(5)真正理解模板技术、特化、萃取等技术的使用和实现,你才会感受到C++的魅力,知道C++为什么效率高
(6)从实用角度讲,不需要真的深度去研究这些。但是如果完全不懂甚至不知道这些技术的存在,那休想用好C++
转载:https://blog.csdn.net/weixin_44705391/article/details/117046835