第七周学习:函数模板

函数模板:模板以泛型编写程序而不是具体类型。这样可以轻松调用同一块内容而数据类型不同的函数。

//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]<<" ";
	
}
  1. 首先要T (为指向某种数据类型的指针),还要Pred(某种指向函数的指针,可以调用函数)
  2. 然后参数要数组头,数组尾,另外一个数组头,然后函数指针四个
  3. 书写平方和立方函数,书写的时候不能用模板了,不然Map这边不知道您什么类型呢。
    4.然后*c = op(*a)
  4. 传进去的是数组名(数组元素类型的指针,以及函数名(指向函数的指针))
Map(arr1,arr1+5,temp,Square);等价于
	//void Map(int* a, int* b, int* c, double (*op)(double))

在这里插入图片描述
很不错。

猜你喜欢

转载自blog.csdn.net/ZmJ6666/article/details/108714882