1、函数模板的定义
template<typename T>
void func(T num)
{
}
未知类型名可以取任意名字,一般约定T
2、函数模板的原理
函数模板会经历俩次编译
1、检查函数模板的语法是否错误,如果无误,也不生成函数的二进制指令,代码段没有存储该函数模板
2、根据调用者提供的实参类型再次编译检查函数模板代码,如果没有错误,才会生成一份二进制指令存储在代码段中,所以,如果函数模板没有任何一次调用则不会生成任何二进制指令,如果有同类型的实参调用函数模板,则会生成另一份二进制指令存储在代码段
这种函数模板实例化称为“惰性实例化”准则
3、函数模板的调用
c++编译器不会把函数模板当作一个函数实体,而是当作生成函数实体的工具,当调用函数模板并提供了实际类型参数后,才会生成函数实体
调用函数模板必须提供相应数量的类型参数 自动:编译器会自动根据实参的类型,获取函数模板的类型 手动:函数名<type1,type2,...>(实参) 会根据<>中提供的类型名取生成函数实体
4、默认形参类型
template<typename T1,typename T2,typename T3=long>
T3 函数名(T1 arg,T2 arg2)
{
T3 ret = arg1+arg2;
return ret;
}
函数模板的类型参数可以像普通函数的默认形参设置形参值一样取设置默认的形参类型,靠右原则一致,但是该语法只有C++11后才支持 不支持的话编译时要加参数 -std=gnu++0x
5、函数模板的特化
模板虽好但不能直接解决所有类型的问题,有一些特殊类型与普通类型的运算规则不同,例如char*,因此需要给这些特殊类型实现一个特殊版本,这种称为函数模板的特化
特化的方式:
1、通过typeid()分支判断类型执行特殊步骤
if(typeid(T)==typeid(char*))
2、实现一个特化版本
特化的格式
template<>
特化类型返回值 函数名(特化类型 形参名){}
附上C++模板技术实现基本类型快速排序以及特化排序类型const char*
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
void _qsort(T* arr,size_t len,int left,int right)
{
if(left>=right) return;
int l=left,r=right,p=left;
T val = arr[p];
while(l<r)
{
while(l<r&&arr[r]>=val) r--;
if(l<r)
{
arr[p] = arr[r];
p = r;
}
while(l<r&&arr[l]<=val) l++;
if(l<r)
{
arr[p] = arr[l];
p = l;
}
arr[p] = val;
_qsort(arr,len,p+1,right);
_qsort(arr,len,left,p-1);
}
}
// 特化版本
template<>
void _qsort(const char* arr[],size_t len,int left,int right)
{
if(left>=right) return;
int l=left,r=right,p=left;
const char* val = arr[p];
while(l<r)
{
while(l<r&&(strcmp(arr[r],val)>=0)) r--;
if(l<r)
{
arr[p] = arr[r];
p = r;
}
while(l<r&&(strcmp(arr[l],val)<=0)) l++;
if(l<r)
{
arr[p] = arr[l];
p = l;
}
arr[p] = val;
_qsort(arr,len,p+1,right);
_qsort(arr,len,left,p-1);
}
}
template<typename T>
void qsort(T* arr,size_t len)
{
_qsort(arr,len,0,len-1);
}
int main(int argc,const char* argv[])
{
const char* str[]={"xijxi","alisjld","asij"};
double arr[]={1.4,2.6,5.7,3.9,34.8,1.2};
qsort(arr,6);
qsort(str,3);
for(int i=0;i<6;i++)
{
cout<<arr[i]<<endl;
}
for(int i=0;i<3;i++)
{
cout<<str[i]<<endl;
}
return 0;
}