C++函数模板浅析

	之前看《Effective C++》,作者将C++分成了四种次语言,分别是C,Object-Oriented C++,Template C++,STL;
今天就来简单分析下模板编程部分;
	参考资料:《C++ primer Plus 第六版》和《Effective C++ 第三版》

一.为什么需要函数模板

先看几个函数:

void swap(int& a,int& b)
{
int temp=a;
a=b;
b=temp;
}
void swap(double&a,double&a)
{
double temp=a;
a=b;
b=temp;
}



	除了变量的类型,函数的内容是一模一样的,如果能有一种通用的模板,能够让程序自己根据类型填空完成函数不就能大大减
少工作量吗?值得高兴的是,C++中的模板功能能完成这一过程:


template<typename T>
void swap(T& a,T& b)
{
T temp=a;
a=b;
b=temp;
}


:注意到的是,在C++98之后才能使用关键字typename,之前都是使用class创建模板的;
调用的时候只需要像普通函数一样调用函数模板就可以了:
int i=2,j=3;
swap(i,j);
这里在编译期间编译器会自动进行参数类型的推演,然后为对应的类型生成模板实例,即生成一个swap的int类型版本的代码,这也是为什么
模板会使得代码的体积膨胀,
----注:我目前尚不知道多次使用相同类型调用函数模板是否会导致创建多个模板实例,等进行实验后回来补充这个问题-----

二.模板的重载

	实际上上面的模板定义是有缺陷的,因为它假定了T类型是可以进行赋值运算的,而实际上有一些类型是不能进行赋值运算的,
对于这些类型,我们就需要定义不同的函数模板了。例如数组,数组是不能进行赋值操作的,所以需要为各种类型的数组定义一个
模板:
	void swap(T a[],T b[],int n);//具体定义略

	这里的模板的特征标为(T [],T[]);而原来的模板的特征标为(T&,T&);
重载就是同一个函数名而特征标不同的一组函数,这里也是满足这个条件的,所以这就是函数模板的重载;
调用的时候依然是像普通函数那样调用就可以了,编译器照样会生成对应版本的代码;
三.显式具体化
然而有些类型使用模板重载也无法做到通用模板,结构类型便是如此;

struct light
{
float R;
float G;
float B;
}
struct name
{
string firstName;
string lastName;
}


	这两种结构类型是没有办法使用通用的模板的void swap(struct T&,struct T&);显然没法进行定义,这个时候就需要使用模板
的显式具体化了-----提供一个具体的函数定义(话说这就是定义一个对应类型的函数出来):
--C++98标准使用了如下的具体化方法
--对于给定的函数名,可以有非模板函数、模板函数和显示具体化模板函数以及它们的重载版本
--显示具体化的原型和定义应以template<>打头,并通过名称来指出类型
--具体化优先于常规模板,而非模板函数优先于具体化和常规模板
例如:
//显式具体化原型
template<> void swap<light>(light&,light&);
其中的<light>是可选的,因为参数类型中以及说明了类型,即可修改为 template<> void swap(light&,light&);

四.具体化和实例化

实例化:编译器根据给出的模板生成对应类型的代码
具体化:直接自己提供完整的函数定义,但是需要遵循上面提到的格式
请注意这两者的微妙差别,实例化是编译器提供代码,而具体话则是程序员自己编写代码;
早期的编译器只能通过隐式实例化,即程序员看不到编译器生成的代码,也不知道编译器生成了代码,也不能控制编译器的代码生成
,而现在C++还允许显示实例化,这意味这可以直接命令编译器创建特定的实例:
	其语法是,声明所需的种类--用<>符号指示类型,并且在声明前面 添加关键字template;
	template void swap<int>(int&,int&); //显示实例化
	函数调用时 swap<int>(i,j);也是显示实例化,但没有中间的<>就是隐式实例化;
	当编译器看到上面这条语句之后编译器会为swap()模板生成int类型的版本的代码

	template<> void swap<int>(int&,int&);//显示具体化
	template<> void swap(int&,int&);//显示具体化
	编译器看到这两条语句后只是知道了代码中有int 版本的代码,并且不会为它生成代码


注意:在同一个文件中使用同一种类型的显示实例和显示具体化将出错

	隐式实例化、显示实例化和显示具体化统称为具体话,它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不
是通用描述;

五.模板的特化和偏特化

这部分有许多作者都讲的比较详细完整,这里就不多做解释了,可以参考这一篇这一篇
函数的特化其实就是显示具体化。
六.待续...



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章