在模板元编程里面,有一种情况是模板特例化,就是你定义了一个模板类,并且专门为它写了一些特例,如下:
//定义了一个模板类Vec
template <class T, int N> class Vec {
public:
Vec() { std::cout << "zero" << std::endl; }
private:
T m_arr[N];
};
//特别注意这个特例化版本,
template <> class Vec<int, 4> {
public:
Vec() { std::cout << "spec" << std::endl; }
private:
float m_arr[4];
};
//完全特例化
template <> class Vec<float, 4> {
public:
Vec() { std::cout << "all" << std::endl; }
private:
float m_arr[4];
};
//部分特例化
template <int N> class Vec<bool, N> {
public:
Vec() { std::cout << "one" << std::endl; }
private:
char m_value[(N + sizeof(char) - 1) / sizeof(char)];
};
通过构造函数打印,我们来看一下具体是具体是怎么调用的:
int main() {
Vec<int, 10> myVec;
Vec<int, 4> myVec1;
Vec<float, 4> myVec2;
Vec<bool, 10> myvec3;
}
输出结果是:
归纳一下:
在定义模板特例之前必须已经有模板通例(primary template)的声明;
模板特例并不要求一定与通例有相同的接口,但为了方便使用(体会特例的语义)一般都相同;
匹配规则,在模板实例化时如果有模板通例、特例加起来多个模板版本可以匹配,则依据如下规则:对版本AB,如果 A 的模板参数取值集合是B的真子集,则优先匹配 A,如果 AB 的模板参数取值集合是“交叉”关系(AB 交集不为空,且不为包含关系),则发生编译错误,对于函数模板,用函数重载分辨(overload resolution)规则和上述规则结合并优先匹配非模板函数
关于最后一条可以看上面代码中的spec打印。