1. 什么是部分特例化(partial specialization)?
“针对模板参数更进一步的条件限制所设计出来的一个特化版本” (摘自《泛型思维》)
//原始的,最通用版本,允许接收T为任何类型
template<typename T>
class C { ... };
//部分特例化,此版本仅适用于指针类型
template<typename T>
class C<T *> { ... };
注:只有类模板才支持部分特例化,函数模板特例化时必须为原模板中每个模板参数都提供实参。
2. 进一步介绍:
类模板的部分特例化版本在本质上还是一个模板。
当我们定义类模板的部分特例化版本时,我们首先定义模板参数(就是template<>中的内容)。特例化版本的模板参数只包含原模板中那些还未确定类型的模板参数。
在类名之后的<>中,我们要为特例化的模板参数指定实参。(注意:这些实参与原模板中的参数按位置对应)
例如:
//general template
template<class T1, class T2>
class Pair { ... };
//specialization with T2 set to int
template<class T1>
class Pair<T1, int> { ... };
上述第二个声明将T2具体化为int,但T1保持不变。
到此,你可能会对文章开始的那个例子感到困惑,在那个例子中特例化版本的模板参数的数目与原始模板相同,怎么叫部分特例化?
其实,部分特例化版本的模板参数列表是原始模板参数列表的一个子集或者是一个特例化版本。在第一个例子中,就是使用指针提供特殊版本来部分实例化现有的模板。
3. 使用部分特例化的类模板
对于class C:
C<char> c1; //use general C template, T is char
C<char *> c2; //use C<T *> partial specialization, T is char
对于class Pair:
Pair<double, double> p1; //use general Pair template
Pair<double, int> p2; //use Pair<T1, int> partial specialization
注:如果有多个模板可供选择,编译器将使用特例化程度最高的模板。
4. 补充:
如果我们对所有的模板参数指定类型,则<>内将为空,这将导致全特例化版本,又叫显示特例化(explicit specialization)。
例如:
//specialization with T1 and T2 set to int
template<>
class Pair<int, int> { ... };
//use Pair<int, int> explicit specialization
Pair<int, int> p3;
参考文献:
《C++ Primer》第五版