Continued form C++ shared library & templates
Here we’ll look at how template functions become linked together when a shared library & header expose a template function to use.
We will create a library liba.so
from the file a.cpp
. The header exposed by the shared library is a.h
. Let’s look at the contents of the files:
a.h
:
template<typename T>
T f() {}
a.cpp
:
#include "a.h"
template void f<void>();
void foo() { f<void>(); }
The (relevant) symbols present in liba.so
are:
0000000000001100 W void f<void>()
00000000000010f0 T foo()
Note that “W” indicates a Weak Symbol.
The user of the shared library is b.cpp
:
#include "a.h"
int main() {
f<void>();
}
And the relevant symbols in the final binary (with the shared library linked) are:
0000000000001129 W void f<void>()
Observe that even though our liba.so
has explicitly instantiated f<void>
, the binary still has the definition of f<void>
present.
If we add the following line to b.cpp
:
extern template void f<void>();
Then the symbol becomes:
U void f<void>()
The extern
declaration makes the type of the symbol as Undefined, means it will be provided through somewhere else. If there is no explicit instantiation of f<void>
in liba.so
, there will be no defined symbol available and linking will fail. Also see C++ extern - Explicit template instantiation