读书笔记--模板(1)

   函数模板时独立于子类型的函数,可作为一种方式。产生函数的特定类型版本,使用函数模板时,编译器会推断那个模板实参,一旦编译器确定了实际的模板实参,就称它实例了函数模板的一个实例。
  inline 说明符放在模板形参表之后,返回类型之前。
template<typename T> inline T Min(const T&,const T&);   //OK
inline template<typename T> T Min(const T&,const T&);   //error

  模板类型的推断:
  compare("hi","world");
  根据第一个实参推断形参,T为char[3],而根据第二个实参推断为char[6,T被推断为两种不同的类型,则会出现编译错误。
 
  与全局作用域中声明的对象,函数或类型同名的模板形参会屏蔽全局名字
  typedef double T;
  template<class T> T calc(const T&a,const T&b)
  {
 //tmp has the type of the template parameter T
 //not that of the global typedef
 T tmp=a;
 ...
 return tmp;
  }
  用作模板形参的名字不能在模板内部重用
template<class T> T calc(const T&a,const T&b)
{
    typedef double T;    //error:redeclares template parameter 
 T tmp=a;
 ...
 return temp;
}
同时也意味着模板形参的名字只能在同一模板形参表中使用一次
template<class V,class V> V calc(const V&,const V&)
//error 有歧义
同一模板的声明和定义中,模板形参的名字不必相同
template<class T> T calc(const T&,const T&);
template<class U> U calc(const U&,const U&);
//two uses of calc refer to the same function template

在模板定义内部指定类型:
如果要在函数模板内部使用能够独立机器的方式的类型,必须显示指定具体类型
tempate<class Parm,class U> Parm fcn(Parm *array,U value)
{
 parm::size_type *p;     //if that is a type,the a declarde
       //if that is an object,then multipican
}
默认情况下,编译器假定这size_type是指定数据成员,而不是类型。可以显示的:
template<class Parm ,class U>Parm fcn(Parm *array,U Value)
{
 typename Parm::size_type *p;      //OK:declars p to be pointer
}
即在成员名前加入typename作为前缀

在调用函数是非类型形参将用值代替,值的类型在模板形参中指定
template<class T,size_t N> void array_init(T(&parm)[N])
{
 for(size_t i=0;i!=N;++i)
 {
  parm[i]=0;
 }
 
}

类型形参的实参的受限转换:
short s1,s2;
int i1,i2;
compare(i1,i2);
compare(s1,s2);
如果compare(int ,int)是普通的非模板函数,则第二个调用会匹配那个函数,short实参将提升为int,一般而言,不会转换实参以匹配已有的实例化,相反,会产生新的实例。编译器指挥执行两种转换:
  1.const转换:接受const引用或const指针的函数可以分别用非const对象的引用或指针来调用,无须产生新的实例化,如果函数接受非引用类型形参和实参都可忽略const
  2.数组或函数到指针的转换:如果模板兴灿不是引用类型,则对数组函数类型的实参应用常规指针转换。数组实参将当作指向其第一个元素的指针,函数实参当作函数类型的指针。
template<typename T> T fobj(T,T);     //arguments are copied
//reference arguments
template<typename T> T fref(const T&,const T&);
string s1("a value");
const string s2("anthor value");
fobj(s1,s2);            //OK:calls f(string,string),const is ignord
fref(s1,s2);            //OK:non const object s1 converted to const reference
int a[10],b[42];
fobj(a,b);              //OK:calls f(int *,int *)
fref(a,b);              //error:array types don't match;arguments aren't converted to pointers

  使用显示模板实参,使得可以传递两个字符串字值调用compare
可以传递三种方式:
1.compare<string>("mary","mac");
2.compare static_cast<string>("mary"),static_cast<string>("mac");
3.compare (string("mary"),string("mac"));
类型转换的限制只适用于类型为模板形参的那些实参,普通类型在实参调用时可常规转换

模板实参推断与函数指针
template<typename T> int compare(const T&,const T&);
int (*pf1)(const int&,const int&)=compare;
pf1是个指针,指向“接受两个const int&类型形参并返回int值得函数”,形参的类型决定了T的模板实参的类型
如果不能从函数指针类型确定模板实参,就会出错
//overload version of func;each take a different function
void func( int (*)(const string &,const string &) );
void func( int (*)(const int &,const int &) );
func(compare);//   error:which instantiation of compare
对func的调用不能确定唯一的实例化,会造成编译错误

 

 

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值