function9-自动推导模板
前言
自动推导的用处配合上模板大概才有真正的火花
正文
1 | int Ave(int a, int b){ |
首先瞅一个函数重载,我们简单做个模板:
1 | template<typename T> |
但是这个模板似乎只能适应第一个函数,为什么呢?
因为T只代表了一个类型,所以当你函数的参数类型不同时,单纯的参数就搞不明白了。
聪明娃一下子就想到用两个参数了:
1 | template<typename T1,typename T2> |
但是这种虽然是两种参数了,而且返回值是根据模板1来的,还是有点糙。
你说用<>
去指定1和2是什么类型的参数,其实意义也没有太大。
且看重载的第三个函数,发现返回值,参数都不相同。。要用模板就要用三个了。
1 | template<typename T1,typename T2,typename T3> |
用三个模板就有不好使的点
- T1和T2可以通过形参去确定类型,返回值似乎就成了孤儿
- 虽然可以指定,但是这种写法就要一次性指定三个了,除非说T1做返回值类型,这样倒是只要做一个指定
1
2
3
4
5
6
7template<typename T1,typename T2,typename T3>
T1 Ave(T2 a, T3 b){
return (a + b) / 2;
}
int main(){
std::cout << Ave<int>(100,200.0f) << "\n";
}
学习了函数模板不要拘束自己的思想:
1 | template<typename T1,typename T2,typename T3> |
虽然上面是给编译器提供了一个模板,但是下面本质还是自定义参数,你仍可以使用它完成函数能完成的操作
玩一玩闹一闹
1 | template<typename T1,typename T2> |
ps: 不同类型直接的引用存在类型转换问题
回顾正式-函数模板参数的默认值
在玩函数的时候我们知道可以给形参赋予默认值,以应对一些情况不是很有必要输入的地方。
1 | int stringL(char &a, int len, bool flag=true){ |
那么函数模板的参数也就是typename T=xxx
之类的操作
1 | template<typename T1=int,typename T2=double> |
拿我们之前说的三个模板参数的问题:
1 | template<typename T1,typename T2,typename T3> |
需要指定一下返回值类型在每次调用的时候都指定也挺累,所以可以使用默认值
1 | template<typename T1=int,typename T2,typename T3> |
还有一种用法就是让一个参数=前面某个参数的类型:
1 | template<typename T1,typename T2,typename T3=T1> |
当然用法归用法,怎么用还得看你想怎么实现。
既然有指定模板类型参数,就衍生了非类型的模板参数
1 | template<typename T1,typename T2,typename T3=T1,int max,int min> |
这样有点不直观,随便找个例子:
1 | template<typename T,int max,int min> |
因为我们忽略了模板max和min。但是这样写在后面,然后你指定的时候它是顺位来的所以要修改一下
1 | template<int max,int min, typename T> |
可以看到hp的值改变了
回过头,max和min算什么?肯定不是变量,因为它俩存在于模板参数定义中。
虽然模板的特色就是替换,但max目前是被替换成了1200,这就是临时的常量,肯定是不能被修改的,有疑惑可以去函数里试试能不能修改max或者min。
然后传递个变量: 看到报错了
但是把x设置为常量:
1 | const int x = 1200; |
这样是没问题的。
也就是说在模板参数里的非类型参数是算常量
最后鸡贼的时候,默认参数默认参数
1 | template<int max=1200,int min=1000, typename T> |
就不需要指定了,默认给了,如果不想改动,一般就放到后面就行了
拓展
利用模板计算数组平均数:
1 | int pj(int *p,int count){ |
但是利用模板,可以让长度达到自适应效果:
1 | template<typename T,short count> |
可以看到传参的时候都不需要用,分隔长度。这也是因为模板自动推敲出了count这个长度的参数
但是不足之处是对于char类型数组,毕竟T是模板,当返回值是一个char类型的值打印出来就很怪。
模板排序大法
1 | template<typename T,unsigned count> |
效果如图,算法采用冒泡,因为写法好记。。。怎么理解冒泡找视频有动画排序的过程加深理解。
结语
- 模板 会根据 类型生成不同的函数重载 : 详情见debug 调用两个不同类型的函数 看call 函数时内存地址
1 | template<class T> |
模板其实还有一种声明类为参数的方式,但是这里目前还是处于面向过程就等后面做到模板类在回顾。