P298
“对于大多数人,首先得和最明显的应用就是定义和使用容器类。”
“在调用模板函数时,函数参数的类型决定了到底应该使用哪个版本,也就是说,模板的参数是由函数推断出来的。”
P299
“对于一个调用,能从函数的参数推断出模板参数的能力是其中最关键的东西。”
“编译器能从一个调用推断出类型参数和非类型参数,条件是:由这个调用的函数参数能够唯一的标识出模板参数的一个集合。
例如:template<class T , int i>T& lookup(Butter<T,i>&b,const char*p);
class Record
{
const char[2];
//...
};
Record& f(Butter<Record,128>& buf,const char *p)
{
return lookup(buf,p); //使用lookup( ),其中T是Record , i是128
} //在这里推断出T是Record,i是128
”
“注意,绝不会对类模板的参数做任何推断。”
“如果不能从模板函数的参数推断出某个模板参数,我们就必须显示地去描述它。
template<class T>class cector{/*...*/};
template<class T>T* create( ); //创建一个T,返回到它的指针
void f( )
{
vector<int>v; //类,模板参数“int”
int* p=create<int>( ); //函数,模板参数“int”
}
”
P300
*关于函数模板的重载
“可以声明多个具有同样名字的函数模板,甚至可以声明具有同样一个名字的多个函数模板和常规函数组合。例如:
template<class T>T sqrt(T);
template<class T>complex<T> sqrt(complex<T>);
double sqrt(double);
void f(complex<double> z)
{
sqrt(2); //sqrt<int>(int)
sqrt(2.0); //sqrt(double)
sqrt(z); //sqrt<double>(complex<double>)
}”
“简而言之,对每个模板,我们都要找出对这个组合函数参数的一组最基佳专门化结果。”
“找出能参与这个重载解析的一组函数模板专门化。”
“如果两个模板函数都可调用,其中一个比另一个更专门,在随后的步骤中就只考虑那个最专门的模板函数。”
“在这组函数上重载解析,包括那些按照常规函数考虑也应该加上去的常规函数。”
“如果一个函数和一个专门化具有同样好的匹配,那么就选用函数。”
“找不到匹配,就是一个错误。”
P302
“所以,任何一种通用的解决方案,都要求排序算法应当以某种通用的方式表述,使它的定义不但可以用于特定类型,而且还可以用于特定类型的特定应用。”
P303
“每次调用都需要显示地给出比较准则也会使人厌烦。还好,很容易确定一种默认方式,这样,就只有那些不平常的比较准则才需要显式地给出。这可以通过重载来实现:
template<class T,class C>
int compare(const String<T>&str1,const String<T>&str2); //用C比较
template<class T>
int compare(const String<T>&str1,const String<T>&str2); //用Cmp<T>比较”
“换一种方式,我们也可以将常规的习惯作为默认模板参数:
template<class T,class C=Cmp<T> > //注意:这里两个> >要有空格。
int compare(const String<T>&str1,const String<T>&str2); ”
P305
“对一个模板的这些可以相互替代的定义称为用户定义类型的专门化,或简称为用户专门化。”
“专门化是一种针对一个共同界面,为不同的使用提供各种可替代的实现的方法。”
P306
“说一个专门化比另一个更专门化,如果能够与它匹配的每个实际参数表也能与另外的那个专门化匹配,但反过来就不是。”
P308
“从一个非模板类派生出一个模板类,这是为一组模板提供一个共用实现的方法。例如:template<class T>class Vector<T*>:private Vector<void *>{/*...*/}
P309
“为了能有所区分,将虚函数提供的东西称作运行时多态性,而把模板提供的称为编译时多态性,或者参数式多态性。”
P310
“如果在这些对象间并不需要某种层次性的关系,那么最好是将它们作为模板的参数。如果在编译时,无法确定这些对象的类型,那最好将它们表示为一个公共抽象类的许多派生类。”
P311
“模板实现的是一种在需要时能够基于用户描述去生成类型的机制,正因为此,类模板有时也被称为类型生成器。”
P313
“分开编译方式:
//out.h
template<class T>void out(const T& t);
//out.c
#include<iostream>
#include“out.h”
export template<class T>void out(const T&t){std::cerr<<t;}
//user.c
#include“out.h”
//使用out( )
为了使其他编译单位能够访问,就必须将这个模板定义显式地声明为export,...如果没有这样做,在任何地方要使用模板,都将要求它的定义必须位于作用域中。
本文地址:http://com.8s8s.com/it/it24655.htm