Инстанцирование
Инстанцирование шаблона – это генерация кода функции или класса по шаблону для конкретных параметров. Различают неявное инстанцирование, которое происходит при вызове функции или создании объекта класса, и явное инстанцирование с помощью резервированного слова
template. Инстанцирование можно делать только в точке программы, где доступна реализация шаблона функции или методов шаблонного класса.
Реализация шаблонов должна быть определена в заголовочном файле, чтобы компилятор смог выполнить инстанцирование шаблона для любых аргументов, но можно скрыть реализацию, используя явное инстанцирование. В заголовочном файле при этом остаётся только объявление шаблонов, а реализация помещается в отдельный файл. Для всех возможных вариантов применения шаблонов в этом модуле выполняется явное инстанцирование. Плюсы: компиляция выполняется быстрее, сохраняется know-how, минус: использование шаблонов с непредусмотренными аргументами приведёт к ошибке при компоновке программы.
Заголовочный файл my.h:
template <typename T> T sqr(T);
template <typename T> class X
{
T x;
public:
X(T x):x(x){}
T get()const;
void set(T);
};
Реализация модуля my.cpp:
#include "my.h"
template <typename T> T sqr(T x)
{ return x*x;
}
template <typename T> T X<T>::get() const
{ return x;
}
template <typename T> void X<T>::set(T x)
{ this->x=x;
}
template double sqr(double); //
template int sqr(int); //
template class X<int>; //
Применение:
#include <iostream>
#include "my.h"
using namespace std;
int main()
{
cout<<sqr(10)<<"\n"; //
cout<<sqr(1.2)<<"\n"; //
cout<<sqr(10L)<<"\n"; //
X<int> x1(10);
cout<<x1.get()<<"\n"; //
X<double> x2(1.2);
cout<<x2.get()<<"\n"; //
return 0;
}
Компилятор производит генерацию кода по шаблону, когда происходит явное или неявное инстанцирование. Это может существенно увеличить время компиляции и компоновки, особенно в тех случаях, когда шаблон инстанцируется с одинаковыми параметрами во многих модулях. С помощью
extern теперь можно указать компилятору не инстанцировать шаблон в данной единице трансляции.
extern template vector<int>;
Естественно, в одном из модулей должно быть сделано явное или неявное инстанцирование, чтобы при компоновке программы все ссылки были разрешены.
template vector<int>; //