printШаблоны

printИнстанцирование

Инстанцирование шаблона – это генерация кода функции или класса по шаблону для конкретных параметров. Различают неявное инстанцирование, которое происходит при вызове функции или создании объекта класса, и явное инстанцирование с помощью резервированного слова 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>;       // и класса для типа int
Применение:
#include <iostream>
#include "my.h"
using namespace std;
int main()
{
  cout<<sqr(10)<<"\n";  // OK
  cout<<sqr(1.2)<<"\n"; // OK
  cout<<sqr(10L)<<"\n"; // Ошибка, нет sqr(long)
  
  X<int> x1(10); 
  cout<<x1.get()<<"\n"; // OK
  X<double> x2(1.2); 
  cout<<x2.get()<<"\n"; // Ошибка, нет X<double>::get()
  return 0;
}

Компилятор производит генерацию кода по шаблону, когда происходит явное или неявное инстанцирование. Это может существенно увеличить время компиляции и компоновки, особенно в тех случаях, когда шаблон инстанцируется с одинаковыми параметрами во многих модулях. С помощью extern теперь можно указать компилятору не инстанцировать шаблон в данной единице трансляции.

extern template vector<int>; 

Естественно, в одном из модулей должно быть сделано явное или неявное инстанцирование, чтобы при компоновке программы все ссылки были разрешены.
template vector<int>; // явное инстанцирование
loading