12.2.2 隐式实例化
函数模板实际上不是个完整的函数定义,因为其中的类型参数还不确定,只是定义了某些类型的角色(或变量)在函数中的操作形式,因此,必须将模板参数实例化后才能使用函数,模板参数实例化后的函数也称为模板函数,最简单的实例化称为“隐式实例化”(Implicit Instantiation)。下面通过示例代码12.3进行说明。
代码12.3 隐式实例化ImplicitInstantiation
<———————————文件名:example1203.cpp———————————————-> 01 #include<iostream> 02 using namespace std; 03 template<class Ex> 04 Ex Greater(Ex x,Ex y);//函数模板的声明 05 int main() 06 { 07 int intX=1,intY=2; 08 double dblX=3. 0,dblY=2.9; 09 cout<<Greater(intX,intY)<<endl;//实参为int型,生成int型模板函数,并对第2个 10 //参数进行检查 11 cout<<Greater(dblX,dblY)<<endl;//实参为double型,生成double型模板函数,并 12 //对第2个参数进行检查 13 return 0; 14 } 15 template<class Ex>//函数模板的定义 16 Ex Greater(Ex x,Ex y) 17 { 18 return x>y?x:y; 19 }
输出结果如下所示。
2 3
【代码解析】之所以叫“隐式实例化”,这是因为函数模板中的类型参数直到该函数真正地被调用时才能决定,并且由编译器根据传递给函数的参数类型自动完成。编译器根据最先遇到的(从左到右)实参隐式生成一个模板函数。如代码第16行定义的一个函数模板Greater用以返回两个同类型值中较大的一个,如下代码所示。
Greater(intX,intY)
编译器根据上述语句第一个参数intX的类型int隐式生成一个模板函数,其原型如下所示。int Greater(int,int):
也就是将Ex替换成int,此时,对函数参数列表中其余的Ex型参数进行类型检查,如果后续的Ex型实参可直接解释为int型,则编译通过,否则,编译器报错。注意,此处的直接解释不包括类型转换的情况,这意味着下述调用的代码是错误的。
Greater(2.5,3);原因在于编译器首先根据2.5将Ex解释为double型参数,其次用double型参数去检查剩余的Ex型参数,而3是int型数据,因此编译器报错。通过显式转换可解决这个问题,如下所示。 Greater(2.5,double(3));
语句“Greater(dblX,dblY)”的执行过程与上述相似。
注意
当存在多个类型参数时,如Ex1,Ex2等,编译器根据这些类型参数对应的第一个实参为其解释类型,并用此类型检查后续参数。