Вам необходимо определить template<typename T> std::string Derived<T>::Foo() { ... }
и template<typename T>
std::string Derived<T>::Bar() { ... }
в заголовочном файле. Когда компилятор компилирует test.cpp, он не знает всех возможных значений T
, которые вы можете использовать в других частях программы.
Я думаю, что есть некоторые компиляторы, которые имеют связи между шагами компиляции и компоновки, которые замечают ссылки на отсутствующие экземпляры шаблона и создают их экземпляры из файла .cpp, где они объявлены. Но я не знаю, какие они есть, а функциональность найти крайне редко.
Если вы определите их в заголовочном файле, большинство компиляторов будут выдавать их как «слабый» символ в каждую единицу компиляции, на которую они ссылаются. И компоновщик выбросит все, кроме одного определения слабого символа. Это вызывает дополнительное время компиляции.
С другой стороны, существуют синтаксисы для явного создания экземпляров шаблонов и принуждения компилятора генерировать определения прямо здесь. Но для этого необходимо знать все значения, которые T
может иметь, и вы неизбежно пропустите некоторые из них.