先额外介绍个知识点,非类型模板参数。
模板参数可以是一个类型,也可以是一个常量,如果是常量,那么这个模板参数就叫做非类型模板参数。
例如STL中的array的实现:
template<class T,class N>
class A
{
public:
typedef size_t iterator;
typedef const size_t const_iterator;
array()
{
size = N;
}
T& operator[](const T& idx)
{
assert(idx < size);
return _a[idx];
}
iterator begin()
{
return 0;
}
iterator end()
{
return size - 1;
}
private:
T arr[N];//固定大小的数组
size_t size;
}
array使用格式:array<类型,数组大小> 对象名;
array<int,100> arr;
array 的成员变量中有一个长度固定的数组arr,array 的模板参数中第二个参数就是N就是非类型模板参数,为常量,在类中可以将该非类型模板参数当成常量来使用;但是也有限制,一般都是整型,浮点型、类、对象、字符串等都是不可以用来做非类型模板参数的。(非类型模板参数必须在编译的时候就能确定)
例如:
//比较函数
template<class T>
bool greater( T left,T right)
{
return left > right;
}
void test()
{
Date d1(2002,2,1);
Date d2(2003,4,9);
cout<<greater(&d1,&d2)<<endl;
//用比较函数比较两个日期,虽然可以成功运行,但是因为我们传参的时候传的是指针类型,那么比较的时候 比较的也就是指针的大小了
}
这个时候模板的特化就派上了用场,就是在原来的模板类基础之上,针对特殊类型所进行特殊化的实现方式。
函数模板特化的规则:
1.必须要有一个基础的函数模板作为前提
2.关键字template后接一个空的<>
3.函数名后跟一对<>,在其中指定需要特化的类型
4.函数形参列表必须要和模板函数参数类型完全相同,如果不同编译器会报错。
//函数模板的特化
template<class T>
bool greater( T left,T right)
{
return left > right;
}
template<>
bool greater<Date*>( Date* left, Date* right)
{
return *left > *right;
}
//一般的函数模板可以不特化 直接给出 类模板一般才特化
bool greater(Date* left, Date* right)
{
return *left > *right;
}
//此时调用下面的函数的时候就会走特化后的比较函数了,得到的就是正确的结果了
void test()
{
Date d1(2002,2,1);
Date d2(2003,4,9);
cout<<greater(&d1,&d2)<<endl;
}
规则与函数模板基本相同。
template<class T1,class T2>
class A
{
public:
A()
{
cout << "A" << endl;
}
};
//全特化
template<>
class A<int,double>
{
public:
A()
{
cout << "A" << endl;
}
};
//以下面的模板为基础模板
template<class A,class B>
class Action
{
public:
Action()
{
cout<<"Action"<<endl;
}
private:
A _a;
B _b;
};
//限制基础模板的第二个模板参数为double类型
template<class A>
class Action<A,double>
{
public:
Action()
{
cout<<"Action"<<endl;
}
private:
A _a;
double _b;
};
//限制第一个模板参数为int 第二个模板参数为 char
template<>
class Action<int,char>
{
public:
Action()
{
cout<<"Action" <<endl;
}
private:
int _a;
char _b;
};
template<class T1,class T2>
class A
{
public:
A()
{
cout << "A" << endl;
}
}
//进一步限制 限制两个参数为都必须为指针类型
template<class T1,class T2>
class A<T1*,T2*>
{
public:
A()
{
cout << "A" << endl;
}
};
//进一步限制第一个参数是指针类型,第二个参数是引用类型
template<class T1,class T2>
class A<T1*,T2&>
{
public:
A()
{
cout << "A" << endl;
}
};