一、类模板的默认模板参数原则
1、可以为类模板的类型形参提供默认值,但不能为函数模板的类型形参提供默认值。函数模板和类模板都可以为模板的非类型形参提供默认值。
2、类模板的类型形参默认值形式为:
template<class T1, class T2=int> class A{};
为第二个模板类型形参T2提供int型的默认值。
3、类模板类型形参默认值和函数的默认参数一样,如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值,比如
template<class T1=int, class T2>class A{};
就是错误的,因为T1给出了默认值,而T2没有设定。
4、在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型。比如
template<class T1, class T2=int> class A{public: void h();};
定义方法为
template<class T1,class T2> void A<T1,T2>::h(){}
二、验证上述原则
template<class T1,class T2=int> class CeilDemo{
public:
int ceil(T1,T2);
};
template<class T1,class T2>
int CeilDemo<T1,T2>::ceil(T1 a,T2 b){
return a>>b;
}
int main(){
CeilDemo<int> cd;
cout<<cd.ceil(8,2.5)<<endl;
return 0;
}
输出2(8右移2位),另外会报一个double转int会丢失信息的warning。
在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型,如果没有省略,可能会依编译器不同有不同的处理方案(之前的vc可能只是报warning),我在vs2012和g++上是报错:
error C4519: 仅允许在类模板上使用默认模板参数
可见这里编译器将这里的默认参数认为是函数模板的。
template<class T1=int,class T2=double,class T3=double> class CeilDemo{
public:
double ceil(T1,T2,T3);
};
template<class T1,class T2,class T3>
double CeilDemo<T1,T2,T3>::ceil(T1 a,T2 b,T3 c){
return a+b+c;
}
void main(){
CeilDemo<> cd;
cout<<cd.ceil(2.5 ,3 ,4)<<endl;
}
输出9
三、测试案例汇总
template<class T>class A{public:T g(T a, T b); A();};
template<class T1,class T2>class B{public:void g();};
template<class T1,class T2=int> class D{public: voidg();};
针是正确的。
template<class T1,int a> class Ci{public:void g();};
template<class T1,int &a>class Cip{public:void g();};
template<class T1,A<int>* m> class Cc{public:void g();};
template<class T1,double*a>class Cd{public:void g();};
class E{}; template<class T1,E &m> class Ce{};
也不例外。
template<class T> A<T>::A(){cout<<"class A goucao"<<typeid(T).name()<<endl;}
template<class T> T A<T>::g(T a,T b){cout<<"class A g(T a,T b)"<<endl;}
template<class T1,class T2> voidB<T1,T2>::g(){cout<<"class g f()"<<typeid(T1).name()<<typeid(T2).name()<<endl;}
template<class T1,int a> voidCi<T1,a>::g(){cout<<"class Ci g()"<<typeid(T1).name()<<endl;}
template<class T1,int &a> voidCip<T1,a>::g(){cout<<"class Cip g()"<<typeid(T1).name()<<endl;}
template<class T1,A<int> *m> voidCc<T1,m>::g(){cout<<"class Cc g()"<<typeid(T1).name()<<endl;}
template<class T1,double* a> voidCd<T1,a>::g(){cout<<"class Cd g()"<<typeid(T1).name()<<endl;}
template<class T1,class T2> voidD<T1,T2>::g(){cout<<"class D g()"<<endl;}
参时,在template的形参表中默认值应省略。
int e=2; doubleed=2.2; double*pe=&ed;
A<int> mw; A<int> *pec=&mw; E me;
int main()
{
A<int> ma;
B<int,int> mb; mb.g();
变量的地址都不是一个常量表达式,都不能用作非类型模板形参的实参。全局指针类型,全局变量,全局对象也不是一个常量表达式,不能
用作非类型模板形参的实参。
Ci<int,3>
const int a2=3; Ci<int,a2> mci1; mci1.g();
Cip<int,e> mcip;
Cd<int,&ed> mcd;
Cc<int,&mw> mcc; mcc.g();
E me1;
Ce<int,me> mce;
const short s=3; Ci<int,s> mci4†
参考资料
[1] http://www.cnblogs.com/gw811/archive/2012/10/25/2736224.html(注:此文有多处问题,请抱着谨慎态度查看)