template służy do generowania "rodziny" klas/funkcji etc. W celu wygenerowania kodu kompilator musi mieć dostęp do definicji. Kompilator kompilując jeden plik .cpp nie pamięta "szczegółów" drugiego pliku .cpp (nosi to nazwę separate compilation model) w którym jest zawarta definicja przez co dostajesz błąd od linkera.
Można to "obejść" w następujący sposób:
// 1.inl
template<typename T>
T foo(T lhs, T rhs) {
return lhs + rhs;
}
// 1.hpp
#ifndef _FOO_HPP
#define _FOO_HPP
template<typename T>
T foo(T lhs, T rhs);
#include "1.inl"
#endif
// main.cpp
#include "1.hpp"
int main(void) {
foo<short>(1, 1);
}
Można jeszcze powiedzieć, że c++11 wprowadził słowo kluczowe export, które ma na celu umożliwiać rozdzielanie wzorców na więcej niż jeden plik aczkolwiek nie jest to implementowane przez większość kompilatorów. Osobiście nie znam żadnego kompilatora, który by to implementował.