Next: Bound member functions,Previous: C++ Interface,Up: C++ Extensions
7.5 Where's the Template?
C++ templates are the first language feature to require moreintelligence from the environment than one usually finds on a UNIXsystem. Somehow the compiler and linker have to make sure that eachtemplate instance occurs exactly once in the executable if it is needed,and not at all otherwise. There are two basic approaches to thisproblem, which are referred to as the Borland model and the Cfront model.
-
Borland model
-
Borland C++ solved the template instantiation problem by adding the codeequivalent of common blocks to their linker; the compiler emits templateinstances in each translation unit that uses them, and the linkercollapses them together. The advantage of this model is that the linkeronly has to consider the object files themselves; there is no externalcomplexity to worry about. This disadvantage is that compilation timeis increased because the template code is being compiled repeatedly. Code written for this model tends to include definitions of alltemplates in the header file, since they must be seen to beinstantiated.
Cfront model
- The AT&T C++ translator, Cfront, solved the template instantiationproblem by creating the notion of a template repository, anautomatically maintained place where template instances are stored. Amore modern version of the repository works as follows: As individualobject files are built, the compiler places any template definitions andinstantiations encountered in the repository. At link time, the linkwrapper adds in the objects in the repository and compiles any neededinstances that were not previously emitted. The advantages of thismodel are more optimal compilation speed and the ability to use thesystem linker; to implement the Borland model a compiler vendor alsoneeds to replace the linker. The disadvantages are vastly increasedcomplexity, and thus potential for error; for some code this can bejust as transparent, but in practice it can been very difficult to buildmultiple programs in one directory and one program in multipledirectories. Code written for this model tends to separate definitionsof non-inline member templates into a separate file, which should becompiled separately.
When used with GNU ld version 2.8 or later on an ELF system such asGNU/Linux or Solaris 2, or on Microsoft Windows, G++ supports theBorland model. On other systems, G++ implements neither automaticmodel.
You have the following options for dealing with template instantiations:
- Compile your template-using code with -frepo. The compilergenerates files with the extension ‘.rpo’ listing all of thetemplate instantiations used in the corresponding object files thatcould be instantiated there; the link wrapper, ‘collect2’,then updates the ‘.rpo’ files to tell the compiler where to placethose instantiations and rebuild any affected object files. Thelink-time overhead is negligible after the first pass, as the compilercontinues to place the instantiations in the same files.
This is your best option for application code written for the Borlandmodel, as it just works. Code written for the Cfront modelneeds to be modified so that the template definitions are available atone 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 templateinstantiations it needs, just try to link all of its object filestogether; the link will fail, but cause the instantiations to begenerated as a side effect. Be warned, however, that this may causeconflicts if multiple libraries try to provide the same instantiations. For greater control, use explicit instantiation as described in the nextoption.
- Compile your code with -fno-implicit-templates to disable theimplicit generation of template instances, and explicitly instantiateall the ones you use. This approach requires more knowledge of exactlywhich instances you need than do the others, but it's lessmysterious and allows greater control. You can scatter the explicitinstantiations throughout your program, perhaps putting them in thetranslation units where the instances are used or the translation unitsthat define the templates themselves; you can put all of the explicitinstantiations you need into one big file; or you can create small fileslike
#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 instantiationlibrary from those.
If you are using Cfront-model code, you can probably get away with notusing -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 tocompile it without -fno-implicit-templates so you get all of theinstances required by your explicit instantiations (but not by anyother files) without having to specify them as well.
The ISO C++ 2011 standard allows forward declaration of explicitinstantiations (with
extern
). G++ supports explicit instantiationdeclarations in C++98 mode and has extended the template instantiationsyntax to support instantiation of the compiler support data for atemplate class (i.e. the vtable) without instantiating any of itsmembers (withinline
), and instantiation of only the static datamembers of a template class, without the support data or memberfunctions (withstatic
):extern template int max (int, int); inline template class Foo<int>; static template class Foo<int>;
- Do nothing. Pretend G++ does implement automatic instantiationmanagement. Code written for the Borland model works fine, buteach translation unit contains instances of each of the templates ituses. In a large program, this can lead to an unacceptable amount of codeduplication.