Специализация
Можно специализировать (изменять реализацию) для определенных типов данных шаблон функции, отдельные методы шаблона класса или шаблон класса целиком.
При специализации функций и отдельных методов допускается только
полная специализация. Перед определением специализации пишется
template <>, а после имени функции или класса добавляется список аргументов основного шаблона в
<>. Аналогичной функциональности можно добиться, если определить обычную функцию или перегрузить шаблон функции. Разница в том, что генерация кода для обычной функции будет происходить при компиляции её определения (т.е. всегда), а для шаблона и специализации – при первом использовании (инстанцировании). Разница между специализацией и перегрузкой шаблона чисто концептуальная.
Пример специализации шаблона функции:
template<>
inline const char * maximum<const char *>(const char *a, const char * b)
{ return strcmp(a,b)>0?a:b;
}
Специализация шаблона класса определяется как шаблон класса, но нельзя указывать значения по умолчанию для параметров шаблона, а после имени класса указывается список аргументов основного шаблона в
<>, который позволяет компилятору установить связь между параметрами специализации и основного шаблона. При специализации шаблона класса можно полностью изменить весь интерфейс класса. Допустима частичная специализация шаблона класса.
Пример специализации шаблона класса:
template <int size> //
class Stack<char *,size> {
char *s[size];
int t;
public:
Stack():t(-1) {} //
bool isEmpty() { return t==-1; }
bool isFull() { return t==size-1; }
~Stack() { while(!isEmpty()) pop(); }
void pop();
const char * top();
void push(const char *);
};
template <int size>
void Stack<char *,size>::pop()
{ if(!isEmpty())
delete[] s[t--];
}
template <int size>
const char * Stack<char *,size>::top()
{ if(isEmpty())
throw StackEmpty();
return s[t];
}
template <int size>
void Stack<char *,size>::push(const char *v)
{ if(isFull())
throw StackFull(); //
s[++t]=new char[strlen(v)+1];
strcpy(s[t],v);
}