I have this function declaration:
template<class T>
a::A& a::A::operator<<(T out) {
std::cout << out;
return (*this);
}
and this function definition:
namespace a {
...
class A {
...
template<class T> A& operator<<(T);
And I call it as:
a::A b;
b << 1;
and this is the Makefile:
app: main.o A.o
g++ main.o A.o -o app
main.o: main.cpp
g++ -c main.cpp
A.o: A.cpp
g++ -c A.cpp
and it gives me:
Undefined symbols: a::A& a::A::operator<< <int>(int)
why is that?
The function template will be turned into an actual function at compile time, once the type represented by
T(that is,intin your case) is actually known. However, this is not the case beforemain.cppis compiled. At the time whenA.cppis compiled, the template function is not instantiated into an actual function, therefore the object file generated doesn’t include the binary version of the function.There are two ways to solve this.
Include the function definition in your header file. That is, make
a part of the header file, and remove the function definition from the
.cppfile.The effect of this is that any
.cppfile that includes this header will be able to use any instantiation of the template, i.e. for any value ofT.Alternatively, include an explicit template instantiation statement in
A.cpp:This will cause the compiler to actually instantiate the template when
A.cppis compiled, and to include the compiled function in the object file. Hence the linker can find it when linkingmain.oandA.otogether, and all is fine. The disadvantage is that it will only work for the specific types (in this case, onlyint) that you provided explicit instantiations for.