编译
1、定义点 编译模板头部
2、调用点 编译模板函数
函数模板
1、函数模板
template<typename E,typename T>
E Sum(E a,T b)
{
return a+b;
}
int main()
{
Sum(10,20.1);
Sum<int>(10,20);
return 0;
}
2、模板函数
template<typename E>
E* Func()
{
E* tmp=new E();
return tmp;
}
int main()
{
Func<void>();
}
3、模板实例化
4、模板的实参推演
1、不能让编译器产生二义性
2、要有实参
#include <iostream>
template <typename T>//<>模板类型参数列表 typename定义一个虚假类型
T Sum(T a,T b)
{
return a+b;
}
template <typename ARR_TYPE>
void Sort(ARR_TYPE *arr,int len)
{
int i=0;
int j=0;
ARR_TYPE tmp=0;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i-1;j++)
{
if(arr[j]>arr[j+1])
{
tmp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=tmp;
}
}
}
}
template<typename T>
void show(T arr[],int len)
{
for(int i=0;i<len;i++)
{
std::cout<<arr[i]<<" ";
}
std::cout<<std::endl;
}
int main()
{
int rt=Sum<int>(10,20);
//Sum(15,25);//实参推演
std::cout<<"int:"<<rt<<std::endl;
int arr[]={1,5,0,8,2,7,2,9,2,10};
int len=sizeof(arr)/sizeof(arr[0]);
Sort<int>(arr,len);
show<int>(arr,len);
}
5、模板的类型参数
typename class
6、模板的非类型参数
1、常量不能修改
2、不能是浮点型 float double
template<class E,double len>
void Sort(E arr[])
{
int i=0;
int j=0;
E tmp=0;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-i-1;j++)
{
tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
int main()
{
int arr[]={12,321,3,12,3,12};
const int len=sizeof(arr)/sizeof(arr[0]);
Sort<int,len>(arr);
const int a=10;
int b=20;
const int c=b;//常量退化成常变量
return 0;
}
7、模板的特例化(模板的版本不能满足特殊类型的需求)
特例化版本的逻辑应该满足和模板版本相同的逻辑
1、完全特例化 全特化 char-*
2、部分特例化 偏特化 T
template <typename T>
bool Compare(T a,T b)
{
std::cout<<"template<typename T:>"<<typeid(T).name()<<std::endl;
return a>b;
}
template<>
bool Compare<char*>(char* const a,char* const b)
{
std::cout<<"template<>:"<<typeid(a).name()<<std::endl;
return strcmp(a,b)>0;
}
int main()
{
Compare(10,20);
Compare<double>(10.1,20);
char* p="hello";
char* q="world";
Compare<char*>(p,q);
return 0;
}
8、模板的默认值 C++11特性
没有指定 不能推演
9、不明确类型的返回值接收
auto
template <typename R=double,typename T1=double,typename T2,typename T3>
R add(T1 a,T2 b,T3 c)
{
std::cout<<typeid(T1).name()<<std::endl;
return a+b+c;
}
int main()
{
auto a=add(10,10.1,20.3);
std::cout<<typeid(a).name()<<std::endl;
return 0;
}
10、模板的重载
普通的函数版本
模板的特例化
模板的版本(实例化的版本)
bool Compare(char* a,char* b)//普通函数版本
{
std::cout << "bool Compare(char*, char*) :" << typeid(a).name() << std::endl;
return strcmp(a,b)>0;
}
template<typename T>//模板的版本
bool Compare(T a,T b)
{
std::cout << "template<typename T>:" << typeid(T).name() << std::endl;
return a>b;
}
template<>//模板的特例化
bool Compare<char*>(char* a, char* b)
{
std::cout << "template<> :" << typeid(a).name() << std::endl;
return strcmp(a, b) > 0;
}
int main()
{
char *p="hello";
char *q="world";
Compare<>(p,q);
Compare(p,q);
return 0;
}
11、模板的显示实例化
模板一般写在.h文件中
#include "lei.h"
template<typename T>
T Sum(T a, T b);
int main()
{
Sum<int>(10,20);
Sum<double>(10.1,20.1);
return 0;
}
template<typename T>
T Sum(T a,T b)
{
return a+b;
}
template int Sum(int,int);
template double Sum(double,double);