Шаблоны на самом деле не производят никакого объектного кода в точке, где компилятор читает их исходный код;они (как правило) только «создаются», когда что-то на самом деле использует шаблон.Таким образом, если вы определяете функцию шаблона в одном исходном файле и вызываете ее из другого, код для функции шаблона вообще не компилируется: он не находится в первом объектном файле, так как ничего ему не нужно, и его нет ввторой объектный файл, так как компилятор не имел доступа к определению функции.
Вы определяете функции шаблона в файлах заголовка, чтобы в каждом модуле перевода, где что-то вызывало функцию шаблона, компилятор имел доступ к своему коду иможно скомпилировать его копию с соответствующими аргументами шаблона.
В качестве альтернативы вы можете использовать явное создание экземпляра : вы определяете функцию шаблона в файле .cpp
, и также сообщает компилятору, для каких типов он должен компилировать функцию.Это сложнее поддерживать, потому что вы должны отслеживать, какие экземпляры нужны остальной части программы.Если что-то вызывает foo<float>()
, но вы только явно создали экземпляры foo<int>()
и foo<char>()
, вы получаете ошибку пропущенного символа.
Вы не должны #include
a .cpp
файл из другого.cpp
файл.Просто поместите определения функций шаблона в заголовок вместе с их объявлениями.