控制实例化:
当模板被使用时才实例化这一特性使得相同的实例可能出现在多个对象文件中,比如当两个或多个独立编译的源文件使用了相同的模板,并提供了相同的模板参数时,每个文件中就都会有一个该模板的实例。
在大系统中,在多个文件中实例化相同模板的额外开销会很严重,在新标准下,可以通过显示实例化来避免这种开销。显示实例化的形式如下:
extern template class Blob<string>; //实例化声明
template int compare(const int& ,cosnt int&); //实例化定义
当编译器遇到extern模板声明的模板声明时,它不会在本文件中生成实例化代码。将一个实例化声明为extern就表示承诺在程序的其他位置有该实例化的一个非extern定义或声明。可以有多个extern声明,但必须只有一个定义。
因此用来显式实例化一个类模板的类型必须能用于模板的所有成员。
模板实参推断:
编译器从函数实参来确定模板实参的过程被称为模板实参推断。
类型转换与模板类型参数:
能在调用中应用于函数模板的类型转换包括以下两项:
1.const装换:可以将一个非const对象的引用(或指针)传递给一个const的引用(或指针)形参;
2.数组或函数指针转换:如果函数形参不是引用类型,则可以对数组或函数类型的实参应用正常的指针转换(一个数组实参可以转换成指向首元素的指针,一个函数实参可以转换成指向该函数的指针)。
其他的类型转换,如算术转换、派生类向基类转换以及用户定义的转换都不能应用于模板。举个栗子:
template <typename T> T fobj(T,T);
template <typename T> T fref(const T&,const T&);
string s1("a value");
const string s2("another value");
fobj(s1,s2); //调用fobj(string,string),const被忽略
fref(s1,s2); //调用fobj(const string&,const string&)
//将s1转换为const的
int a[10],b[10];
fobj(a,b); //调用fobj(int*,int*)
fref(a,b); //错误,数组类型不匹配
正常类型转换应用于普通函数实参
函数模板可以有普通类型定义的参数:
template <typename T> opstream& print(ostream& os,const T& obj){
return os<<obj;
}
第一个参数是已知类型,其类型是固定的,传递给他的实参会进行正常的类型转换:
print(cout 10); //实例化print(ostream&,int)
ofstream f("output");
print(f,42); //调用print(ostream&,int),将f转换为ostream&