Частично специализация шаблонов класса (C++)
Шаблоны класса могут быть частично специализировать, а результирующий класс по-прежнему шаблон.Частично специализация шаблона позволяет коду частично для настройки определенных ситуациях типов, например:
Шаблон содержит несколько типов и только некоторые из них требуется специальное.Результат шаблон параметризованный на остальных типов.
Шаблон имеет только один тип, однако специализация, необходимые для указателя, ссылки указателя на член или типов указателя функции.Специализация шаблона сама остается ссылочного типа указанному значение.
Пример
// partial_specialization_of_class_templates.cpp
template <class T> struct PTS {
enum {
IsPointer = 0,
IsPointerToDataMember = 0
};
};
template <class T> struct PTS<T*> {
enum {
IsPointer = 1,
IsPointerToDataMember = 0
};
};
template <class T, class U> struct PTS<T U::*> {
enum {
IsPointer = 0,
IsPointerToDataMember = 1
};
};
struct S{};
extern "C" int printf_s(const char*,...);
int main() {
S s, *pS;
int S::*ptm;
printf_s("PTS<S>::IsPointer == %d PTS<S>::IsPointerToDataMember == %d\n",
PTS<S>::IsPointer, PTS<S>:: IsPointerToDataMember);
printf_s("PTS<S*>::IsPointer == %d PTS<S*>::IsPointerToDataMember ==%d\n"
, PTS<S*>::IsPointer, PTS<S*>:: IsPointerToDataMember);
printf_s("PTS<int S::*>::IsPointer == %d PTS"
"<int S::*>::IsPointerToDataMember == %d\n",
PTS<int S::*>::IsPointer, PTS<int S::*>::
IsPointerToDataMember);
}
Если имеется класс коллекции шаблона, который принимает любой тип Тможно создать частично специализация, которая принимает любой тип указателя T*.В следующем примере кода демонстрируется шаблон класса коллекции Bag и частично специализация для типов, которым разыменование указателя с внутренней коллекции типы указателей перед копированием их в массив.Коллекция затем сохраняет значения, укажите пункты.С исходным шаблоном, но сами указатели хранились в коллекции, оставляя данные уязвимой для drop или изменению.В этой особой версии указателя коллекции, код для проверки нулевого указателя в add метод добавляется.
// partial_specialization_of_class_templates2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
// Original template collection class.
template <class T> class Bag {
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 <class T> class Bag<T*> {
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<int> xi;
Bag<char> xc;
Bag<int*> xp; // Uses partial specialization for pointer types.
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);
p = NULL;
xp.add(p);
xp.print();
}
В следующем примере определяется класс шаблона, который принимает пары любом из 2 типов и затем определяет частично создания специализированного класса специализацию шаблона, чтобы один из типов будет int.Специализация задает дополнительный метод сортировки, реализующий простой сортировки пузырька на основе целом числе.
// partial_specialization_of_class_templates3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class Key, class Value> class Dictionary {
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 <class Value> class Dictionary<int, Value> {
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<char*, char*>* dict = new Dictionary<char*, char*>(10);
dict->print();
dict->add("apple", "fruit");
dict->add("banana", "fruit");
dict->add("dog", "animal");
dict->print();
Dictionary<int, char*>* dict_specialized = new Dictionary<int, char*>(10);
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();
}