类模板可以部分专用化,生成的类仍是模板。 在类似于下面的情况下,部分专用化允许为特定类型部分自定义模板代码:
模板有多个类型,且只有一部分需要专用化。 结果是基于其余类型参数化的模板。
模板只有一个类型,但指针、引用、指向成员的指针或函数指针类型需要专用化。 专用化本身仍是指向或引用的类型上的模板。
示例:类模板的部分专用化
// partial_specialization_of_class_templates.cpp
#include
template
enum {
IsPointer = 0,
IsPointerToDataMember = 0
};
};
template
enum {
IsPointer = 1,
IsPointerToDataMember = 0
};
};
template
enum {
IsPointer = 0,
IsPointerToDataMember = 1
};
};
struct S{};
int main() {
printf_s("PTS::IsPointer == %d \nPTS::IsPointerToDataMember == %d\n",
PTS::IsPointer, PTS:: IsPointerToDataMember);
printf_s("PTS::IsPointer == %d \nPTS::IsPointerToDataMember == %d\n"
, PTS::IsPointer, PTS:: IsPointerToDataMember);
printf_s("PTS
"
PTS
IsPointerToDataMember);
}
PTS::IsPointer == 0
PTS::IsPointerToDataMember == 0
PTS::IsPointer == 1
PTS::IsPointerToDataMember == 0
PTS
PTS
示例:指针类型的部分专用化
如果有一个采用任何 T 类型的模板集合类,则可以创建采用任何指针类型 T* 的部分专用化。 以下代码演示了一个集合类模板 Bag 以及指针类型的部分专用化,在此专用化中,该集合在将指针类型复制到数组前取消引用它们。 该集合随后存储指向的值。 对于原始模板,只有指针本身将存储在集合中,从而使数据易受删除或修改。 在此特殊指针版本的集合中,添加了在 add 方法中检查 null 指针的代码。
// partial_specialization_of_class_templates2.cpp
// compile with: /EHsc
#include
using namespace std;
// Original template collection class.
template
T* elem;
int size;
int max_size;
public:
Bag() : elem(0), size(0), max_size(1) {}
void add(T t) {
T* tmp;
if (size + 1 >= max_size) {
max_size *= 2;
tmp = new T [max_size];
for (int i = 0; i < size; i++)
tmp[i] = elem[i];
tmp[size++] = t;
delete[] elem;
elem = tmp;
}
else
elem[size++] = t;
}
void print() {
for (int i = 0; i < size; i++)
cout << elem[i] << " ";
cout << endl;
}
};
// Template partial specialization for pointer types.
// The collection has been modified to check for NULL
// and store types pointed to.
template
T* elem;
int size;
int max_size;
public:
Bag() : elem(0), size(0), max_size(1) {}
void add(T* t) {
T* tmp;
if (t == NULL) { // Check for NULL
cout << "Null pointer!" << endl;
return;
}
if (size + 1 >= max_size) {
max_size *= 2;
tmp = new T [max_size];
for (int i = 0; i < size; i++)
tmp[i] = elem[i];
tmp[size++] = *t; // Dereference
delete[] elem;
elem = tmp;
}
else
elem[size++] = *t; // Dereference
}
void print() {
for (int i = 0; i < size; i++)
cout << elem[i] << " ";
cout << endl;
}
};
int main() {
Bag
Bag
Bag
xi.add(10);
xi.add(9);
xi.add(8);
xi.print();
xc.add('a');
xc.add('b');
xc.add('c');
xc.print();
int i = 3, j = 87, *p = new int[2];
*p = 8;
*(p + 1) = 100;
xp.add(&i);
xp.add(&j);
xp.add(p);
xp.add(p + 1);
delete[] p;
p = NULL;
xp.add(p);
xp.print();
}
10 9 8
a b c
Null pointer!
3 87 8 100
示例:定义部分专用化,使一种类型为 int
以下示例定义了一个采用由任意两种类型构成的对的模板类,然后定义已专用化的模板类的部分专用化,使其中一个类型为 int。 该专用化定义了基于整数实现简单气泡排序的另一种排序方法。
// partial_specialization_of_class_templates3.cpp
// compile with: /EHsc
#include
using namespace std;
template
Key* keys;
Value* values;
int size;
int max_size;
public:
Dictionary(int initial_size) : size(0) {
max_size = 1;
while (initial_size >= max_size)
max_size *= 2;
keys = new Key[max_size];
values = new Value[max_size];
}
void add(Key key, Value value) {
Key* tmpKey;
Value* tmpVal;
if (size + 1 >= max_size) {
max_size *= 2;
tmpKey = new Key [max_size];
tmpVal = new Value [max_size];
for (int i = 0; i < size; i++) {
tmpKey[i] = keys[i];
tmpVal[i] = values[i];
}
tmpKey[size] = key;
tmpVal[size] = value;
delete[] keys;
delete[] values;
keys = tmpKey;
values = tmpVal;
}
else {
keys[size] = key;
values[size] = value;
}
size++;
}
void print() {
for (int i = 0; i < size; i++)
cout << "{" << keys[i] << ", " << values[i] << "}" << endl;
}
};
// Template partial specialization: Key is specified to be int.
template
int* keys;
Value* values;
int size;
int max_size;
public:
Dictionary(int initial_size) : size(0) {
max_size = 1;
while (initial_size >= max_size)
max_size *= 2;
keys = new int[max_size];
values = new Value[max_size];
}
void add(int key, Value value) {
int* tmpKey;
Value* tmpVal;
if (size + 1 >= max_size) {
max_size *= 2;
tmpKey = new int [max_size];
tmpVal = new Value [max_size];
for (int i = 0; i < size; i++) {
tmpKey[i] = keys[i];
tmpVal[i] = values[i];
}
tmpKey[size] = key;
tmpVal[size] = value;
delete[] keys;
delete[] values;
keys = tmpKey;
values = tmpVal;
}
else {
keys[size] = key;
values[size] = value;
}
size++;
}
void sort() {
// Sort method is defined.
int smallest = 0;
for (int i = 0; i < size - 1; i++) {
for (int j = i; j < size; j++) {
if (keys[j] < keys[smallest])
smallest = j;
}
swap(keys[i], keys[smallest]);
swap(values[i], values[smallest]);
}
}
void print() {
for (int i = 0; i < size; i++)
cout << "{" << keys[i] << ", " << values[i] << "}" << endl;
}
};
int main() {
Dictionary
dict.print();
dict.add("apple", "fruit");
dict.add("banana", "fruit");
dict.add("dog", "animal");
dict.print();
Dictionary
dict_specialized.print();
dict_specialized.add(100, "apple");
dict_specialized.add(101, "banana");
dict_specialized.add(103, "dog");
dict_specialized.add(89, "cat");
dict_specialized.print();
dict_specialized.sort();
cout << endl << "Sorted list:" << endl;
dict_specialized.print();
}
{apple, fruit}
{banana, fruit}
{dog, animal}
{100, apple}
{101, banana}
{103, dog}
{89, cat}
Sorted list:
{89, cat}
{100, apple}
{101, banana}
{103, dog}