Здесь определяется член шаблона класса, у которого есть один параметр типа шаблона Т
. Сам член является шаблоном функции, имеющий параметр типа It
.
Чтобы создать экземпляр шаблона-члена шаблона класса, следует предоставить аргументы для параметров шаблона и класса, и функции. Как обычно, аргументы для параметров шаблона класса определяются типом объекта, через который происходит вызов шаблона-члена. Так же как обычно, компилятор, как правило, выводит тип аргументов шаблона для собственных параметров шаблона-члена из аргументов, переданных при вызове (см. раздел 16.1.1):
int ia[] = {0,1,2,3,4,5,6,7,8,9};
vector
list
//
//
Blob
//
//
Blob
//
//
Blob
При определении a1
указывается явно, что компилятор должен создать экземпляр шаблона Blob
с параметром типа int
. Параметр типа для его собственных параметров конструктора будет выведен из типа результатов вызова функций begin(ia)
и end(ia)
. Этим типом является int*
. Таким образом, определение a1
создает следующий экземпляр:
Blob
Определение а2
использует уже готовый экземпляр класса Blob
и создает экземпляр конструктора с параметром типа It
, замененным на vector
. Определение a3
(явно) создает экземпляр шаблона Blob
с собственным параметром шаблона типа string
и (неявно) экземпляр конструктора шаблона-члена этого класса с собственным параметром типа list
.
Упражнение 16.21. Напишите собственную версию типа DebugDelete
.
Упражнение 16.22. Пересмотрите программы TextQuery
из раздела 12.3 так, чтобы указатель-член shared_ptr
использовал тип DebugDelete
как свою функцию удаления (см. раздел 12.1.4).
Упражнение 16.23. Предскажите, когда будет выполняться оператор вызова в вашей основной программе запроса. Если предсказание неправильно, убедитесь, что понимаете почему.
Упражнение 16.24. Добавьте в свой шаблон Blob
конструктор, получающий два итератора.
Тот факт, что экземпляр шаблона создается только при его использовании (см. раздел 16.1.1), означает, что создание того же экземпляра может происходить в нескольких объектных файлах. Когда два или более отдельно откомпилированных файла исходного кода используют тот же шаблон с теми же аргументами шаблона, создание экземпляра этого шаблона осуществляется в каждом из этих файлов.
extern template объявление; //
template объявление; //
где
— это объявление класса или функции, в котором все параметры шаблона заменены аргументами шаблона. Например:
//
extern template class Blob
template int compare(const int&, const int&); //
Когда компилятор встретит внешнее (extern
) объявление шаблона, он не будет создавать код его экземпляра в этом файле. Объявление экземпляра как extern
является обещанием того, что будет и не внешнее создание экземпляра в другом месте программы. Вполне может быть несколько внешних объявлений для каждого экземпляра, однако по крайней мере одно определение экземпляра должно быть.
Поскольку компилятор автоматически создает экземпляр шаблона при его использовании, объявление extern
должно располагаться перед любым кодом, который использует этот экземпляр:
//
//