В качестве примера обычного класса, у которого есть шаблон-член, определим класс, подобный стандартному типу функции удаления (deleter), используемой указателем unique_ptr (см. раздел 12.1.5). Как и у стандартной функции удаления, у данного класса будет перегруженный оператор вызова функции (см. раздел 14.8), который, получив указатель, выполняет для него оператор delete. В отличие от стандартной функции удаления, новый класс будет также выводить сообщения при каждом запуске. Поскольку создаваемую функцию удаления предстоит использовать с любым типом, сделаем оператор вызова шаблоном:
// класс объекта функции, вызывающий оператор delete для указателя
class DebugDelete {
public:
DebugDelete(std::ostream &s = std::cerr): os(s) { }
//
template
{ os << "deleting unique_ptr" << std::endl; delete p; }
private:
std::ostream &os
};
Как и любой другой шаблон, шаблон-член начинается с собственного списка параметров шаблона. У каждого объекта класса DebugDelete есть переменная-член типа ostream для вывода и функция-член, которая сама является шаблоном. Этот класс можно использовать вместо оператора delete:
double* p = new double;
DebugDelete d; //
d(p); //
int* ip = new int;
//
DebugDelete()(ip);
Поскольку вызов объекта DebugDelete удаляет переданный ему указатель, его можно также использовать как функцию удаления для указателя unique_ptr. Чтобы переопределить функцию удаления указателя unique_ptr, укажем тип функции удаления в скобках и предоставим объект типа функции удаления конструктору (см. раздел 12.1.5):
//
//
unique_ptr
//
//
unique_ptr
Здесь указано, что у функции удаления p будет тип DebugDelete и что предоставлен безымянный объект этого типа в конструкторе p().
Деструктор класса unique_ptr вызывает оператор вызова типа DebugDelete. Таким образом, при каждом вызове деструктора класса unique_ptr создается также экземпляр оператора вызова класса DebugDelete. Таким образом, определения выше создадут следующие экземпляры:
//
void DebugDelete::operator()(int *p) const { delete p; }
void DebugDelete::operator()(string *p) const { delete p; }
Шаблон-член можно также определить и для шаблона класса. В данном случае у и класса, и у его члена будут собственные, независимые параметры шаблона.
В качестве примера снабдим класс Blob конструктором, который получает два итератора, обозначающих диапазон копируемых элементов. Поскольку желательно обеспечить поддержку итераторов в различных видах последовательностей, сделаем этот конструктор шаблоном:
template
template
// ...
};
У этого конструктора есть свой собственный параметр типа шаблона, It, который он использует для типа двух параметров функции.
В отличие от обычных функций-членов шаблонов класса, шаблоны-члены
template
template
Blob
data(std::make_shared