Исходные файлы компилируются независимо друг от друга в исполняемый код, а затем связываются с основной программой. Шаблонные функции, с другой стороны, не могут быть скомпилированы без параметров шаблона. Таким образом, файл, который использует их, должен иметь этот код для его компиляции. Поэтому функции должны быть видны в заголовочном файле.
Обещанный пример:
template<class T>
void swap(T & a, T & b)
{
T temp = a;
a = b;
b = temp;
}
Единственные требования к классу T здесь заключаются в том, что он имеет открытый оператор присваивания (=). Это почти каждый класс, который когда-либо был реализован или задуман. Однако каждый класс реализует оператор присваивания по-своему. Один и тот же машинный код не может быть сгенерирован для swap , swap и swap . Каждая из этих функций должна быть уникальной. В то же время компилятор не может предвидеть все множество различных типов, которые вы можете передать этой функции, поэтому он не может генерировать функции заранее. Поэтому он должен ждать, пока функция не будет вызвана, а затем он может быть скомпилирован.
Например, допустим, у меня есть функция, определенная выше, в "swap.h". Затем в "main.cpp" я делаю это:
int main()
{
int a=5, b=10;
double c=3.5, d=7.9;
string s1="hello";
string s2="world";
swap(a,b);
swap(c,d);
swap(s1,s2);
}
В этом примере были созданы 3 разные функции. Один, чтобы поменять местами, один, чтобы обменять двойники, и один, чтобы поменять местами строки. Чтобы создать эти функции, компилятор должен был видеть код шаблона. Если бы он находился в отдельном исходном файле, например, «swap.cpp», компилятор не смог бы его увидеть, потому что, как я уже говорил, каждый исходный файл компилируется независимо друг от друга.