Częściowe specjalizacji klasy szablonów (C++)
Częściowo wyspecjalizowane klasy szablonów i klasy wynikowy jest nadal szablonu.Częściowe specjalizacji umożliwia kod szablonu do częściowo dostosowania dla określonych typów w sytuacjach, takich jak:
Szablon zawiera wiele typów i tylko niektóre muszą być wyspecjalizowany.Wynik jest szablon sparametryzowana na pozostałych typów.
Szablon zawiera tylko jeden typ, ale specjalizacji jest wymagany dla wskaźnik, odwołanie, wskaźnik, aby Członek lub typów wskaźników funkcji.Specjalizacji, sam jest nadal szablonu typu wskazał, lub do których odwołuje się.
Przykład
// 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);
}
Jeśli masz szablonu klasy kolekcji, że trwa dowolnego typu t, można utworzyć częściowe specjalizacji, że trwa dowolnego typu wskaźnik T *.Poniższy kod demonstruje szablonu klasy kolekcji Bag i częściowe specjalizacji dla typów wskaźników, w których kolekcji rozstrzyga typów wskaźników przed skopiowaniem ich do tablicy.Kolekcja, następnie przechowuje wartości, które są wskazywanego.Na podstawie oryginalnego szablonu same kursory byłoby były przechowywane w kolekcji, narażając danych do usunięcia lub modyfikacji.W tej wersji wskaźnik specjalne kolekcji kod Aby sprawdzić, czy wskaźnik zerowy w add dodaje się metody.
// 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();
}
Poniższy przykład definiuje szablonu klasy, która zajmuje par jakichkolwiek dwóch typów i następnie definiuje częściowe specjalizacji danej klasy szablonu wyspecjalizowane tak, że jeden z typów jest int.Specjalizacji definiuje metody sortowanie dodatkowe, który implementuje bąbelkowego proste sortowanie oparte na całkowitej.
// 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();
}