(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, 모든 포인터 형식을 사용 하는 부분 특수화를 만들 수 있습니다 T *.컬렉션 클래스 템플릿에 다음 코드를 보여줍니다 Bag 및 부분 특수화에 대 한 포인터 형식에서 컬렉션 역참조 포인터 형식의 배열에 복사 합니다.그런 다음 컬렉션에 지정 된 값을 저장 합니다.원본 템플릿으로 포인터 자체가 데이터를 삭제 또는 수정에 내 컬렉션에 저장 된 것입니다.이 컬렉션의 특별 한 포인터 버전에서 코드를 null 포인터에 대 한 확인은 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();
}
템플릿을 다음 예제 정의 두 가지 종류의 쌍을 가져와 다음 부분 특수화는 템플릿 클래스를 정의 하는 클래스 특수화 된 형식 중 하나를 수 있도록 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();
}