Function Templates 函数模板——初窥

1.1Function Template初窥

所谓的function templates是指由参数化手段表现一整个族群的function。

一个function templates可以表示一族(一整群)functions,其表现和一般的function并无二致,只是其中某些元素在编写时尚未确定,换而言之,那些[尚未确定的元素]被[参数化]了。

1.1.1定义Template
下面的function templates传回两个数值中的较大者:

template < typename T >
inline T 
const   &  max( T  const   &  a, T  const   &  b )
{
    
return a < b ? b : a
}

这一份template定义式代表了一整族functions,他们的作用都是传回a和b两参数中的较大者。两个参数的型别都尚未确定,我们说它"template parameter T"。如你所见,template parameters必须以如此形式加以宣告:

 template<以逗号分隔的参数列>
上述例子中,参数列就是typename T。请注意,例子中的[<]和[>]在这里被当作尖括号使用。关键字typename引入了一个所谓的type parameter(型别参数)------这是目前为止C++程式中最常使用的一种template parameter,另还存在其他种类的template parameter(如:nontype parameter,[非型别参数]),这个以后讨论。

此处的型别参数是T,你也可以使用其他任何标识符号(identifier)来表示型别参数,但习惯写成T(译注:代表Type)。Type parameter可标识任何型别,在function templates被呼叫时,经由传输具体型别而使T得以被具体指定。你可以使用任何型别,只要它支持T所要完成的操作。本列中型别T必须支援operator<以比较两值大小。

由于历史因素,你也可以使用关键字class代替关键字typename来定义一个type parameter。关键字typename是C++发展晚期才引进的,在此之前只能经由关键字class引入type parameter。关键字class目前依然可以用。因此template max()也可以被写成如下等价形式:

template < class  T >
inline T 
const   &  max(T  const   &  a, T  const   &  b)
{
    
return a < b ? b : a;
}

就语义而言,前后两者毫无区别。即便使用关键字class,你还是可以把任意型别(包括non-class型别)当作实际的template arguments。但是这么写可能带来一些误导(让人误以为T必须是class型别),所以最好还是使用关键字typename。请注意,这和class的型别宣告并不是同一回事:宣告type parameters时我们不能把关键字typename换成关键字struct。

1.1.2使用Template
以下程式示范如何使用max() function template:

#include  < iostream >
#include 
< string >
#include 
" max.hpp "

int  main()
{
    
int i = 42;
    std::cout
<<"max(7,i): "<<::max(7,i)<<std::endl;
 
    
double f1 = 3.4;
    
double f2 = -6.7;
    std::cout
<<"max(f1,f2): "<<::max(f1,f2)<<std::endl;

    std::
string s1 = "mathematics";
    std::
string s2 = "math";
    std::cout
<<"max(s1,s2): "<<::max(s1,s2)<<std::endl;
}

程序呼叫了max()三次。第一次参数是两个int,第二次参数是两个double,最后一次参数是两个std::string。每一次max()均比较两值取大者。程序运行结果为:

max( 7 ,i):  42
max(f1,f2): 
3.4
max(s1,s2): mathematics

注意程序对max()的三次呼叫都加了前缀符号"::",以遍确保被唤起的是我们在全域名空间(global namespace)中定义的max()。标准程序库内也有一个std::max() template,可能会在某些情况下被唤起,或在呼叫时引起模棱两可(ambiguity,歧义性,如果某个引数的型别定义于namespace std中,例如string,根据C++搜寻规则,::max()和std::max()都会被找到,那就会引起歧义性)。

 一般而言,templates不会被编译为[能够处理任意型别]的单一实物(entity),而是被编译为多个个别实物,每一个处理某一特定型别。([一份实物,适用所有型别],理论上成立,实际不可行。毕竟所有语言规则都奠基于[将会产生出不同实物]的概念all language rules are based on the concept that different entities are generated)。因此,针对三个型别,max()被编译成三个实物。

例如第一次呼叫max():
int  i  =   42 ;
...max(
7 ,i)...

使用的是[以int为template parameter T]的funciton template,语义上等同于呼叫以下函数:

inline  int   const   &  max( int   const   &  a,  int   const   &  b)
{
    
return a < b ? b : a;
}

以具体型别替换template parameters的过程称为[具现化](instantiation,或称[实体化])。过程中会产生template的一份实体(instance)。不巧的是,instantiation和instance这两个术语在OO(面向对象)编程领域中有其他含义,通常用来表示一个class的具体物件(concrete object)。

注意,只要function template被使用,就会自动引发具现化过程。程序员没有必要个别申请具现过程。

类似情况,另两次对max()的呼叫被具现化为:

const   double   &  max( double   const   & double   const   & );
const  std:: string   &  max(std:: string   const   & , std:: string   const   & );

 如果试图以某个型别来具现化function template,而该型别并未支援function template中用到的操作,就会导致编译错误。例如:

std::complex < float > c1, c2;   // 此型别并不提供operator<
... 
max(c1,c2);                 
// 编译期出错

实际上,template会被编译两次:

1.不具现化,只是对template程序代码进行语法检查以发现诸如[缺少分号;]等等的语法错误。

2.具现化,编译器检查template程序代码中的所有呼叫是否合法,诸如[未授支援函数调用]便会在这个阶段被检查出来。

这会导致一个严重问题:当function template被运用而引发具现化过程时,某些时候编译器需要用到template的原始定义。一般情况下,对普通的(non-template)functions而言,编译和连结两步骤是各自独立的,编译器只检查各个functions的宣告式是否和呼叫式相符,然后template的编译破坏了这个规则。眼下我们用最简单的解法:把template程序代码以inline形式写在表头档(header)中。

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值