gcc: Template Instantiation
1
1 7.5 Where's the Template?
1 =========================
1
1 C++ templates were the first language feature to require more
1 intelligence from the environment than was traditionally found on a UNIX
1 system. Somehow the compiler and linker have to make sure that each
1 template instance occurs exactly once in the executable if it is needed,
1 and not at all otherwise. There are two basic approaches to this
1 problem, which are referred to as the Borland model and the Cfront
1 model.
1
1 Borland model
1 Borland C++ solved the template instantiation problem by adding the
1 code equivalent of common blocks to their linker; the compiler
1 emits template instances in each translation unit that uses them,
1 and the linker collapses them together. The advantage of this
1 model is that the linker only has to consider the object files
1 themselves; there is no external complexity to worry about. The
1 disadvantage is that compilation time is increased because the
1 template code is being compiled repeatedly. Code written for this
1 model tends to include definitions of all templates in the header
1 file, since they must be seen to be instantiated.
1
1 Cfront model
1 The AT&T C++ translator, Cfront, solved the template instantiation
1 problem by creating the notion of a template repository, an
1 automatically maintained place where template instances are stored.
1 A more modern version of the repository works as follows: As
1 individual object files are built, the compiler places any template
1 definitions and instantiations encountered in the repository. At
1 link time, the link wrapper adds in the objects in the repository
1 and compiles any needed instances that were not previously emitted.
1 The advantages of this model are more optimal compilation speed and
1 the ability to use the system linker; to implement the Borland
1 model a compiler vendor also needs to replace the linker. The
1 disadvantages are vastly increased complexity, and thus potential
1 for error; for some code this can be just as transparent, but in
1 practice it can been very difficult to build multiple programs in
1 one directory and one program in multiple directories. Code
1 written for this model tends to separate definitions of non-inline
1 member templates into a separate file, which should be compiled
1 separately.
1
1 G++ implements the Borland model on targets where the linker supports
1 it, including ELF targets (such as GNU/Linux), Mac OS X and Microsoft
1 Windows. Otherwise G++ implements neither automatic model.
1
1 You have the following options for dealing with template
1 instantiations:
1
1 1. Do nothing. Code written for the Borland model works fine, but
1 each translation unit contains instances of each of the templates
1 it uses. The duplicate instances will be discarded by the linker,
1 but in a large program, this can lead to an unacceptable amount of
1 code duplication in object files or shared libraries.
1
1 Duplicate instances of a template can be avoided by defining an
1 explicit instantiation in one object file, and preventing the
1 compiler from doing implicit instantiations in any other object
1 files by using an explicit instantiation declaration, using the
1 'extern template' syntax:
1
1 extern template int max (int, int);
1
1 This syntax is defined in the C++ 2011 standard, but has been
1 supported by G++ and other compilers since well before 2011.
1
1 Explicit instantiations can be used for the largest or most
1 frequently duplicated instances, without having to know exactly
1 which other instances are used in the rest of the program. You can
1 scatter the explicit instantiations throughout your program,
1 perhaps putting them in the translation units where the instances
1 are used or the translation units that define the templates
1 themselves; you can put all of the explicit instantiations you need
1 into one big file; or you can create small files like
1
1 #include "Foo.h"
1 #include "Foo.cc"
1
1 template class Foo<int>;
1 template ostream& operator <<
1 (ostream&, const Foo<int>&);
1
1 for each of the instances you need, and create a template
1 instantiation library from those.
1
1 This is the simplest option, but also offers flexibility and
1 fine-grained control when necessary. It is also the most portable
1 alternative and programs using this approach will work with most
1 modern compilers.
1
1 2. Compile your template-using code with '-frepo'. The compiler
1 generates files with the extension '.rpo' listing all of the
1 template instantiations used in the corresponding object files that
1 could be instantiated there; the link wrapper, 'collect2', then
1 updates the '.rpo' files to tell the compiler where to place those
1 instantiations and rebuild any affected object files. The
1 link-time overhead is negligible after the first pass, as the
1 compiler continues to place the instantiations in the same files.
1
1 This can be a suitable option for application code written for the
1 Borland model, as it usually just works. Code written for the
1 Cfront model needs to be modified so that the template definitions
1 are available at one or more points of instantiation; usually this
1 is as simple as adding '#include <tmethods.cc>' to the end of each
1 template header.
1
1 For library code, if you want the library to provide all of the
1 template instantiations it needs, just try to link all of its
1 object files together; the link will fail, but cause the
1 instantiations to be generated as a side effect. Be warned,
1 however, that this may cause conflicts if multiple libraries try to
1 provide the same instantiations. For greater control, use explicit
1 instantiation as described in the next option.
1
1 3. Compile your code with '-fno-implicit-templates' to disable the
1 implicit generation of template instances, and explicitly
1 instantiate all the ones you use. This approach requires more
1 knowledge of exactly which instances you need than do the others,
1 but it's less mysterious and allows greater control if you want to
1 ensure that only the intended instances are used.
1
1 If you are using Cfront-model code, you can probably get away with
1 not using '-fno-implicit-templates' when compiling files that don't
1 '#include' the member template definitions.
1
1 If you use one big file to do the instantiations, you may want to
1 compile it without '-fno-implicit-templates' so you get all of the
1 instances required by your explicit instantiations (but not by any
1 other files) without having to specify them as well.
1
1 In addition to forward declaration of explicit instantiations (with
1 'extern'), G++ has extended the template instantiation syntax to
1 support instantiation of the compiler support data for a template
1 class (i.e. the vtable) without instantiating any of its members
1 (with 'inline'), and instantiation of only the static data members
1 of a template class, without the support data or member functions
1 (with 'static'):
1
1 inline template class Foo<int>;
1 static template class Foo<int>;
1