7.4.3 Explicit template instantiation
To achieve complete control over the compilation of templates with
g++
it is possible to require explicit instantiation of each
occurrence of a template, using the option
-fno-implicit-templates
. This method is not needed when
using the GNU Linker--it is an alternative provided for systems with
linkers which cannot eliminate duplicate definitions of template
functions in object files.
In this approach, template functions are no longer compiled at the point
where they are used, as a result of the -fno-implicit-templates
option. Instead, the compiler looks for an explicit instantiation of
the template using the template
keyword with a specific type to
force its compilation (this is a GNU extension to the standard
behavior). These instantiations are typically placed in a separate
source file, which is then compiled to make an object file containing
all the template functions required by a program. This ensures that
each template appears in only one object file, and is compatible with
linkers which cannot eliminate duplicate definitions in object files.
For example, the following file 'templates.cc' contains an explicit
instantiation of the Buffer<float>
class used by the program
'tprog.cc' given above:
#include "buffer.h"
template class Buffer<float>;
The whole program can be compiled and linked using explicit
instantiation with the following commands:
$ g++ -Wall -fno-implicit-templates -c tprog.cc
$ g++ -Wall -fno-implicit-templates -c templates.cc
$ g++ tprog.o templates.o
$ ./a.out
stored value = 1.25
The object code for all the template functions is contained in the file
'templates.o'. There is no object code for template functions in
'tprog.o' when it is compiled with the -fno-implicit-templates
option.
If the program is modified to use additional types, then further
explicit instantiations can be added to the file 'templates.cc'.
For example, the following code adds instantiations for Buffer objects
containing double
and int
values:
#include "buffer.h"
template class Buffer<float>;
template class Buffer<double>;
template class Buffer<int>;
The disadvantage of explicit instantiation is that it is necessary to
know which template types are needed by the program. For a complicated
program this may be difficult to determine in advance. Any missing
template instantiations can be determined at link time, however, and
added to the list of explicit instantiations, by noting which functions
are undefined.
Explicit instantiation can also be used to make libraries of precompiled
template functions, by creating an object file containing all the
required instantiations of a template function (as in the file
'templates.cc' above). For example, the object file created from
the template instantiations above contains the machine code needed for
Buffer classes with 'float', 'double' and 'int' types,
and could be distributed in a library.