GNU Info

Info Node: (gcc-295.info)Template Instantiation

(gcc-295.info)Template Instantiation


Next: Bound member functions Prev: C++ Interface Up: C++ Extensions
Enter node , (file) or (file)node

Where's the Template?
=====================

   C++ templates are the first language feature to require more
intelligence from the environment than one usually finds on a UNIX
system.  Somehow the compiler and linker have to make sure that each
template instance occurs exactly once in the executable if it is needed,
and not at all otherwise.  There are two basic approaches to this
problem, which I will refer to as the Borland model and the Cfront
model.

Borland model
     Borland C++ solved the template instantiation problem by adding
     the code equivalent of common blocks to their linker; the compiler
     emits template instances in each translation unit that uses them,
     and the linker collapses them together.  The advantage of this
     model is that the linker only has to consider the object files
     themselves; there is no external complexity to worry about.  This
     disadvantage is that compilation time is increased because the
     template code is being compiled repeatedly.  Code written for this
     model tends to include definitions of all templates in the header
     file, since they must be seen to be instantiated.

Cfront model
     The AT&T C++ translator, Cfront, solved the template instantiation
     problem by creating the notion of a template repository, an
     automatically maintained place where template instances are
     stored.  A more modern version of the repository works as follows:
     As individual object files are built, the compiler places any
     template definitions and instantiations encountered in the
     repository.  At link time, the link wrapper adds in the objects in
     the repository and compiles any needed instances that were not
     previously emitted.  The advantages of this model are more optimal
     compilation speed and the ability to use the system linker; to
     implement the Borland model a compiler vendor also needs to
     replace the linker.  The disadvantages are vastly increased
     complexity, and thus potential for error; for some code this can be
     just as transparent, but in practice it can been very difficult to
     build multiple programs in one directory and one program in
     multiple directories.  Code written for this model tends to
     separate definitions of non-inline member templates into a
     separate file, which should be compiled separately.

   When used with GNU ld version 2.8 or later on an ELF system such as
Linux/GNU or Solaris 2, or on Microsoft Windows, g++ supports the
Borland model.  On other systems, g++ implements neither automatic
model.

   A future version of g++ will support a hybrid model whereby the
compiler will emit any instantiations for which the template definition
is included in the compile, and store template definitions and
instantiation context information into the object file for the rest.
The link wrapper will extract that information as necessary and invoke
the compiler to produce the remaining instantiations.  The linker will
then combine duplicate instantiations.

   In the mean time, you have the following options for dealing with
template instantiations:

  1. Compile your template-using code with `-frepo'.  The compiler will
     generate files with the extension `.rpo' listing all of the
     template instantiations used in the corresponding object files
     which could be instantiated there; the link wrapper, `collect2',
     will then update the `.rpo' files to tell the compiler where to
     place those instantiations and rebuild any affected object files.
     The link-time overhead is negligible after the first pass, as the
     compiler will continue to place the instantiations in the same
     files.

     This is your best option for application code written for the
     Borland model, as it will just work.  Code written for the Cfront
     model will need to be modified so that the template definitions
     are available at one or more points of instantiation; usually this
     is as simple as adding `#include <tmethods.cc>' to the end of each
     template header.

     For library code, if you want the library to provide all of the
     template instantiations it needs, just try to link all of its
     object files together; the link will fail, but cause the
     instantiations to be generated as a side effect.  Be warned,
     however, that this may cause conflicts if multiple libraries try
     to provide the same instantiations.  For greater control, use
     explicit instantiation as described in the next option.

  2. Compile your code with `-fno-implicit-templates' to disable the
     implicit generation of template instances, and explicitly
     instantiate all the ones you use.  This approach requires more
     knowledge of exactly which instances you need than do the others,
     but it's less mysterious and allows greater control.  You can
     scatter the explicit instantiations throughout your program,
     perhaps putting them in the translation units where the instances
     are used or the translation units that define the templates
     themselves; you can put all of the explicit instantiations you
     need into one big file; or you can create small files like

          #include "Foo.h"
          #include "Foo.cc"
          
          template class Foo<int>;
          template ostream& operator <<
                          (ostream&, const Foo<int>&);

     for each of the instances you need, and create a template
     instantiation library from those.

     If you are using Cfront-model code, you can probably get away with
     not using `-fno-implicit-templates' when compiling files that don't
     `#include' the member template definitions.

     If you use one big file to do the instantiations, you may want to
     compile it without `-fno-implicit-templates' so you get all of the
     instances required by your explicit instantiations (but not by any
     other files) without having to specify them as well.

     g++ has extended the template instantiation syntax outlined in the
     Working Paper to allow forward declaration of explicit
     instantiations and instantiation of the compiler support data for
     a template class (i.e. the vtable) without instantiating any of
     its members:

          extern template int max (int, int);
          inline template class Foo<int>;

  3. Do nothing.  Pretend g++ does implement automatic instantiation
     management.  Code written for the Borland model will work fine, but
     each translation unit will contain instances of each of the
     templates it uses.  In a large program, this can lead to an
     unacceptable amount of code duplication.

  4. Add `#pragma interface' to all files containing template
     definitions.  For each of these files, add `#pragma implementation
     "FILENAME"' to the top of some `.C' file which `#include's it.
     Then compile everything with `-fexternal-templates'.  The
     templates will then only be expanded in the translation unit which
     implements them (i.e. has a `#pragma implementation' line for the
     file where they live); all other files will use external
     references.  If you're lucky, everything should work properly.  If
     you get undefined symbol errors, you need to make sure that each
     template instance which is used in the program is used in the file
     which implements that template.  If you don't have any use for a
     particular instance in that file, you can just instantiate it
     explicitly, using the syntax from the latest C++ working paper:

          template class A<int>;
          template ostream& operator << (ostream&, const A<int>&);

     This strategy will work with code written for either model.  If
     you are using code written for the Cfront model, the file
     containing a class template and the file containing its member
     templates should be implemented in the same translation unit.

     A slight variation on this approach is to instead use the flag
     `-falt-external-templates'; this flag causes template instances to
     be emitted in the translation unit that implements the header
     where they are first instantiated, rather than the one which
     implements the file where the templates are defined.  This header
     must be the same in all translation units, or things are likely to
     break.

     Note: Declarations and Definitions in One Header,
     for more discussion of these pragmas.


automatically generated by info2www version 1.2.2.9