C++中有类模板和函数模板,它们的定义如下所示:
类模板:
template<class T1,class T2>
class C
{
//...
};
函数模板:
template<class T1,class T2>
void func(T1 p1,T2 p2)
{
//...
};
特化包括全特化和偏特化,全特化也叫简称特化,所以说特化的时候意思就是全特化。
特化就是对所有的模板参数指定一个特定的类型,偏特化就是对部分模板参数指定特定的类型。
类模板的特化:
template<class T1,class T2> //这里是类模板
class C
{
//...
};
template<> //这里是对C的特化
class C<int,int>
{
//...
};
从语法上看,全特化的时候,template后面尖括号里面的模板参数列表必须是空的,表示该特化版本没有模板参数,全部都被特化了。
类模板的偏特化:
template<class T1,class T2> //这里是类模板
class C
{
//...
};
template <class T1> //这里是对C的偏特化
class C<T1,int>
{
//...
};
从语法上看,偏特化的时候,template后面的尖括号里面的模板参数列表必须列出未特化的模板参数。同时在C后面要全部列出模板参数,同时指定特化的类型,比如指定int为T2的特化类型。
函数模板的特化:
template<class T1,class T2> //这里是函数模板
void func(T1 p1,T2 p2)
{
//...
};
template <> //这里是对函数模板的特化
void func(int p1,int p2)
{
//...
};
函数模板的偏特化:
函数模板不能进行偏特化!!!!!
STL中iterator_traits的偏特化
STL中的iterator_traits用来返回iterator中定义好的五种类型。其具体实现应该是(摘录自STL源码剖析)
template <class I>
struct iterator_traits
{
typedef typename I::iterator_category iterator_category;
typedef typename I::value_type value_type;
typedef typename I::differenct_type difference_type;
typedef typename I::pointer pointer;
typedef typename I::reference reference;
};
因为指针也是一种iterator,如果将指针作为模板参数,上面的定义就会失效。因此上面的模板必须对指针进行特化。特化的代码如下所示:
template <class T> //对iterator_traits的偏特化
struct iterator_traits<T*>
{
typedef ... iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
}
template <class T> //对iterator_traits的偏特化
struct iterator_traits<const T*>
{
typedef ... iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
}
为啥上面要对T* 和const T*进行偏特化,仅对I*进行偏特化不够么?
不够的,如果只对I*进行偏特化,iterator_traits<const int*>::value_type的类型就是const int。这一般不会是我们想要的,所以必须对const I*也进行特化。