函数模板:模板以泛型编写程序而不是具体类型。这样可以轻松调用同一块内容而数据类型不同的函数。
//Swap函数(ps.不要using了std命名空间还命名swap,会有二义性冲突)
template <class T>
void Swap(T& a,T& b)
{
T temp =a;
a = b;
b = temp;
}
struct stu
{
double a;
double b;
};
template<> void Swap(stu& stu1,stu& stu2)
{
cout<<"This is explicit specialization\n";
double temp1 = stu1.a,temp2= stu1.b;
stu1.a = stu2.a;
stu1.b = stu2.b;
stu2.a = stu1.a;
stu2.b = stu1.b;
}
下面那种定义叫显式具体化(explicit specialization),它这样另外定义的作用是,当函数是这种类型的参数时,执行不同的内容。(多用于比如结构,类等与普通数据类型有点不一样的类型)
// 两种类型的参数&&decltype关键字
template<class T1, class T2>
auto ADD(T1 a, T2 b)->decltype(a+b)
{
decltype(a+b) sum =a+b;
return sum; //也可以直接return a+b
}
模板可以提供两个类型,可能想等可能不相等,whatever. 但如果知道它返回什么类型呢,如果a+b,它又是什么类型呢。
decltype
关键字就帮你解决这个问题,decltype(a+b)就是返回一个a+b的类型。
那返回类型又咋搞呢,返回类型实在有参数之前就写好的,那么就用auto
先占个位,然后后面->decltype(a+b)
就是将auto指明为这种类型。
//main.cpp
int main()
{
int i=5,j=8;
double x=4.3,y=6.9;
stu s1{
9.9,8.8},s2{
7.7,6.6};
auto sum1 = ADD(i,j);
auto sum2 = ADD(i,x);
auto sum3 = ADD(x,y);
cout.precision(3);
cout.setf(ios::fixed,ios::floatfield);
cout<<"sum1: "<<sum1<<endl<<"sum2: "<<sum2<<endl<<"sum3: "<<sum3<<endl;
cout<<"before swapping: "<<i<<" "<<j<<endl;
Swap(i,j);
cout<<"After swapping: "<<i<<" "<<j<<endl;
cout<<"before swapping: "<<x<<" "<<y<<endl;
Swap(x,y);
cout<<"After swapping: "<<x<<" "<<y<<endl;
cout<<"Structure s1 before swapping: "<<s1.a<<" "<<s1.b<<endl;
swap(s1,s2);
cout<<"Structure s1 after swapping: "<<s1.a<<" "<<s1.b<<endl;
cout<<"explicit instantialization ADD(i,j):(int to double) "<<ADD<double>(i,j)<<endl;
return 0;
}
Swap(i,j)
这种叫隐式实例化,将T实例化为int;
ADD<double>(i,j)
这种叫具体实例化,不用管参数是啥,T就是double
关于几个sum,函数将自动类型转换,不用你cao heart.
outcome:
函数同名时编译器调用顺序
匹配的普通函数>显式实例化模板函数
>显式具体化模板函数>隐式实例化模板函数
>经自动转换OK的普通函数
截图来自北大mooc:
一个参数为指针的例子
一个可以使数组各个成员进行立法或平方的程序
#include<iostream>
#include<iomanip>
using namespace std;
template<class T, class Pred>
void Map(T a,T b,T c, Pred op) //T为指针,Pred为函数指针
{
for(;a!=b;a++,c++)
{
*c = op(*a);
}
}
int Cube(int x) {
return x*x*x;}
double Square(double x){
return x*x;}
int main()
{
int arr1[5]{
1,2,3,4,5},temp[5];
double arr2[5]{
1.1,2.2,3.3,4.4,10.5},temp2[5];
Map(arr1,arr1+5,temp,Square);
//void Map(int* a, int* b, int* c, double (*op)(double))
for(int i=0;i<5;i++)
cout<<temp[i]<<" ";
cout<<endl;
Map(arr1,arr1+5,temp,Cube);
for(int i=0;i<5;i++)
cout<<temp[i]<<" ";
cout<<endl;
Map(arr2,arr2+5,temp2,Square);
for(int i=0;i<5;i++)
cout<<fixed<<setprecision(2)<<temp2[i]<<" ";
}
- 首先要T (为指向某种数据类型的指针),还要Pred(某种指向函数的指针,可以调用函数)
- 然后参数要数组头,数组尾,另外一个数组头,然后函数指针四个
- 书写平方和立方函数,书写的时候不能用模板了,不然Map这边不知道您什么类型呢。
4.然后*c = op(*a)
- 传进去的是数组名(数组元素类型的指针,以及函数名(指向函数的指针))
Map(arr1,arr1+5,temp,Square);等价于 //void Map(int* a, int* b, int* c, double (*op)(double))
很不错。