首先,我们给出模板函数和模板类的定义:
template <typename T>
void swap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
return;
}
template <typename T>
class myClass {
//details omitted
};
隐式实例化 (implicit instantiation)
- 对于函数模板来说,只需在程序中直接调用参数即可。编译器会根据参数的类型,根据通用模板,自动生成对应的具体类型的函数定义。比如直接使用:
double dNum = 12.2;
double dNum2 = 4.4;
swap(dNum, dNum2);
- 对于类模板来说,隐式实例化 的方式如下:
myClass<int> myObj;
需要注意的一点,隐式实例化时,编译器在需要对象之前,不会生成类的定义。
myClass<int> *myObjPtr; //只是类的指针,还没有生成对象
myObjPtr = new myClass<int>; //现在才生成了一个类对象
在第二条语句,即new之后,编译器才根据通用模板来生成类的定义,并根据该定义创建了一个对象。
显式实例化 (explicit instantiation)
显式实例化 ,使用的关键字叫做 template 。
- 对于函数模板来说,具体用法如下:
template void swap<int>(int, int);
- 对于类模板来说,很相似:
template class myClass<int>;
在这种情况下,虽然没有创建或提及类对象,但是编译器也将会生成类定义。和隐式实例化一样,显式实例化也将根据通用模板来生成定义。
显式特化(explicit specialization)
显式特化,有些地方也翻译为 显式具体化,指的是同一个内容。使用的关键字为 template<> 。
因为有时候,对于特殊类型实例化时,我们需要的行为与通用模板的定义不太一致。此时,就要用到显式特化(explicit specialization)。
- 对于函数模板来说,具体用法如下:
template<> void swap<int>(int&, int &);
//or
template<> void swap(int&, int &);
- 对于类模板来说,具体用法如下:
template<>
class myClass<int> {
//details omitted
}
注意,在同一个文件或转换单元中,使用同一种类型的显式实例化和显式特化将会编译出错。即不能对相同的类型,同时使用explicit instantiation和explicit specialization。
最后,还要讲一点,这一点也很重要。
部分特化(partial specialization)
部分特化可以给类型参数之一指定具体的类型:
//general template
template <typename T1, typename T2> class Pair { };
//partial specialization with T2 set to int
template <typename T1> class Pair<T1, int> { };
关键字template后面的<>声明的是没有被特化的类型参数。因此,上述第二个声明将T2特化为int,但T1保持不变。注意,如果指定所有的类型,那么<>将为空,这就变成了显式特化(explicit specialization)。
//explicit specialization with T1 and T2 set to int
template<> class Pair<int, int> { };