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,...如果没有这样做,在任何地方要使用模板,都将要求它的定义必须位于作用域中。

|