Next:Extracting the Function Pointer from a Bound Pointer to Member Function, Previous:C++ Interface and Implementation Pragmas, Up:Extensions to the C++ Language [Contents][Index]
C++ templates were the first language feature to require moreintelligence from the environment than was traditionally found 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 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. The 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.
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.
G++ implements the Borland model on targets where the linker supports it,including ELF targets (such as GNU/Linux), macOS and Microsoft Windows.Otherwise G++ implements neither automatic model.
You have the following options for dealing with template instantiations:
Duplicate instances of a template can be avoided by defining an explicitinstantiation in one object file, and preventing the compiler from doingimplicit instantiations in any other object files by using an explicitinstantiation declaration, using theextern template syntax:
extern template int max (int, int);
This syntax is defined in the C++ 2011 standard, but has been supported byG++ and other compilers since well before 2011.
Explicit instantiations can be used for the largest or most frequentlyduplicated instances, without having to know exactly which other instancesare used in the rest of the program. 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.
This is the simplest option, but also offers flexibility andfine-grained control when necessary. It is also the most portablealternative and programs using this approach will work with most moderncompilers.
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.
In addition to forward declaration of explicit instantiations(withextern), G++ 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):
inline template class Foo<int>;static template class Foo<int>;
Next:Extracting the Function Pointer from a Bound Pointer to Member Function, Previous:C++ Interface and Implementation Pragmas, Up:Extensions to the C++ Language [Contents][Index]