If a library wants to provide templates which its clients can instantiate with arbitrary types, it must provide the templates' complete definitions in header files. This is why a lot of C++ libraries, including most of Boost, are header-only. The compiler then has access to the template's definition and can instantiate it with any types/values the client provides as template arguments.
For a detailed treatment of the topic, please refer to the Stack Overflow question Why can templates only be implemented in the header file?.
Note that this only applies if, as I said, the templates are intended for use with arbitrary types. If the set of instantiations is limited and can be determined at the time the shared library is built, the library can create explicit instantiations of all the templates it wants all combinations of template arguments it wants to support. Then, exposing the definitions of the templates is not necessary, but of course, it will not be possible to instantiate the templates with different types in client code.
As an example of this, there are some geometric libraries which provide their definitions as templates so that they can work with both float
and double
to represent floating-point numbers, but do not expose the template definitions; they simply pre-instantiate all their code with float
and double
. Clients can then use these instantiations, but cannot use them with for exmaple long double
or MyCustomFloat
.