1.模板的参数列表里除了普通的typename T这样的类型参数之外,还可以定义非类型参数,其表示一个值而不是一个类型。并且这个非类型参数是一个常量值,可以用来指定数组大小。
例子:
template <int a,int b> bool CmpStr(const char(&x) [a],const char(&y) [b]){ return strcmp(x,y)==0; }
2.编译器遇到一个模板定义时并不会立刻生成代码,只有当我们实例化出模板的一个特定版本时,编译器才会生成代码。
所以在编译模板本身时,编译器只能找找分号丢失或者变量名拼错之类的错误。
比如:
template <typename T> bool IfMax(const T& a,const T& b){ return not a<=b; }
如果调用某个自定义类型A:IfMax(A x,A y);
但是A类没有重载小于等于符,那么这个错误只有到实例化的时候才会报错,毕竟之前编译器也根本无从得知你会如何调用模板!
另外,如果模板类的一个成员函数没有被使用,则它不会被实例化。成员函数只有在用到的时候才会被实例化。
3.定义在模板内部的成员函数会被隐式声明为内联函数。
4.可以声明类的友元为类、模板类,模板类的友元为类、模板类。
模板类的友元模板类:
1 template<typename T> class BlobPtr; 2 template<typename T> class Blob; 3 4 template<typename T> bool operator==(const Blob<T>&, const Blob<T>&); 5 6 template<typename T> class Blob{ 7 template<typename X> friend class BlobPtr;//一对多,即任何类型的Blobstr类都是友元 8 //template<typename T> friend class BlobPtr;//一对一,只有T类型的BlobPtr类才是友元 9 friend bool operator==(const Blob<T>& a, const Blob<T>& b); 10 };
5.不能使用typedef定义一个不确定的模板类,如:typedef Blob<T> sb; 这样是错误的!
但我们可以这样写:template<typename T1,typename T2> using twin=pair<T1,T2>;
1 template<typename T1,typename T2> using twin=pair<T1,T2>; 2 int main() { 3 twin<int,double> x={1, 2.7}; 4 cout<<x.first<<" "<<x.second; 5 getchar(); 6 return 0; 7 }
7.如果T是一个模板类的类型参数
T::x有两种含义,一种x为T的静态成员函数/变量,或者x是T类中定义的某种类型,举例如下:
1 class MyArray 2 { 3 public: 4 typedef int LengthType; 5 static f(){cout<<"9527";} 6 }; 7 8 template<typename T> void MyMethod( T myarr ) 9 { 10 typedef typename T::LengthType LengthType; 11 T::f(); 12 }
对于第10行,T::LengthType实际是个类型。
第11行T::f实际是T类的静态成员函数。
对于编译器来说,必须在实例化时确定T::xx到底表示什么。所以如果是变量类型,我们前面要加上typename显式告知编译器后面是一个类型,如果不加编译时会报错。
8.模板函数也可以是inline或者constexpr的,要加在模板参数后面,如:
template<typename t1,typename t2,typename t3> inline constexpr void f(t1 x1,t2 x2,t3 x3){ cout<<x1<<x2<<x3; }
9.一个模板temp<T>每次使用都会实例化,一个文件中的所有对该模板的相同调用(如temp<int>和temp<double>不是同一实例,会实例化两次)共用同一个实例。
但不同文件(CPP)中对该模板的相同调用也会导致多次实例化,避免的方法是先实例化声明再使用该模板。
比如你要使用temp<int>,那么你可以在文件开头声明:extern template class temp<int>; 其中的extern表示temp<int>模板的实例化一定在其他一个文件中,那么在这个文件中我们就可以直接使用temp<int>了。
注意模板实际实例化的头文件一定要include进来!
10.普通类/模板类中的成员函数也可以是带模板的,称为成员模板