В качестве примера обычного класса, у которого есть шаблон-член, определим класс, подобный стандартному типу функции удаления (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