The information in this chapter is derived from the C++ Front End Internal Documentation, Version 2.45, copyright 1992-2000, by the Edison Design Group. Used by the permission of the authors.
The C++ programming language includes the concept of templates . A template is a description of a class or function that is a model for a family of related classes or functions. Because templates are descriptions of entities (typically, classes) that are parameterizable according to the types they operate upon, they are sometimes called parameterized types. For example, you can write a template for a Stack class and then use a stack of integers, a stack of floats, and a stack of a user-defined type. In the source code, these might be written as follows:
Stack<int> Stack<float> Stack<X> |
From a single source description of the template for a stack, the compiler can create an instantiation of the template for each of the types that is required.
The instantiation of a class template is done as soon as it is needed in a compilation. However, the instantiations of template functions, member functions of template classes, and static data members of template classes (hereafter referred to as template entities) are not necessarily done immediately for the following reasons:
You should have only one copy of each instantiated entity across all the object files that make up a program. (This applies to entities with an external linkage.)
You can write a specialization of a template entity. (For example, you can write a version either of Stack<int>, or of just Stack<int>::push, that replaces the template-generated version. Often, this kind of specialization provides a more efficient representation for a particular data type.) When compiling a reference to a template entity, the compiler does not know if a specialization for that entity will be provided in another compilation. Therefore, the compiler cannot do the instantiation automatically in any source file that references it.
You cannot compile template functions that are not referenced. Such functions might contain semantic errors that would prevent them from being compiled. A reference to a template class should not automatically instantiate all the member functions of that class.
![]() | Note: Certain template entities are always instantiated when used (for example, inline functions). |
If the compiler is responsible for doing all the instantiations automatically, it can do so only on a program-wide basis. The compiler cannot make decisions about instantiation of template entities until it has seen all the source files that make up a complete program.
By default, CC performs automatic instantiation at link time. If more explicit control is needed, instantiation modes and instantiation pragmas are also provided and can be used to provide fine-grained control over the instantiation process.
The following subsections discuss methods of instantiation and other associated topics.
Automatic instantiation enables you to compile source files to object code, link them, run the resulting program, and never worry about how the necessary instantiations are done.
The CC(1) command requires that for each instantiation you have a normal, top-level, explicitly compiled source file that contains the definition of the template entity, a reference that causes the instantiation, and declarations of any types required for the particular instantiation.
You can meet the instantiation requirements in several ways:
You can have each header file that declares a template entity contain either the definition of the entity or another file that contains the definition.
When the compiler encounters a template declaration in a header file and discovers a need to instantiate that entity, you can give it permission to search for an associated definition file having the same base name and a different suffix. The compiler implicitly includes that file at the end of the compilation. See “Implicit Inclusion” for more information.
You can make sure that the files that define template entities also have the definitions of all the available types, and add code or #pragma directives in those files to request instantiation of the entities they contain.
The following steps outline the general process for using automatic instantiation.
The first time the source files of a program are compiled, no template entities are instantiated. However, template information files (with a default .ti suffix) are generated and contain information about things that could have been instantiated in each compilation.
When the object files are linked together, a program called the prelinker is run. It examines the object files, looking for references and definitions of template entities, and for the added information about entities that could be instantiated.
If the prelinker finds a reference to a template entity for which there is no definition anywhere in the set of object files, it looks for a file that indicates that it could instantiate that template entity. When it finds such a file, it assigns the instantiation to it. The set of instantiations assigned to a given file (for example, abc.C) is recorded in an associated .ii file (for example, abc.ii). All .ii files are stored in a directory named ii_files created within your object file directory.
The prelinker then executes the compiler again to recompile each file for which the .ii file was changed. The original compilation command-line options (saved in the information file) are used for the recompilation.
When a file is compiled, the compiler reads the .ii file for that file and obeys the instantiation requests therein. It produces a new object file containing the requested template entities (and all the other things that were already in the object file). The compiler also receives a definition list file, which lists all the instantiations for which definitions already exist in the set of object files. If during compilation the compiler has the opportunity to instantiate a reference entity that is not on that list, it goes ahead and does the instantiation. It passes back to the prelinker (in the definition list file) a list of the instantiations that it has 'adopted' in this way, so the prelinker can assign them to the file. This 'adoption' process allows rapid instantiation and assignment of instantiations referenced from new instantiations, and reduces the need to recompile a given file more than once during the prelinking process.
The prelinker repeats steps 3-5 until there are no more instantiations to be adjusted.
The object files are linked.
After the program has been linked correctly, the .ii files contain a complete set of instantiation assignments. From then on, whenever source files are recompiled, the compiler will consult the .ii files and do the indicated instantiations as it does the normal compilations. Except in cases where the set of required instantiations changes, the prelink step will find that all the necessary instantiations are present in the object files and that no instantiation assignment adjustments need be done. This is true even if the entire program is recompiled.
If you provide a specialization of a template entity somewhere in the program, the specialization will be seen as a definition by the prelinker. Becasue that definition satisfies whatever references there might be to that entity, the prelinker sees no need to request an instantiation of the entity. If you add a specialization to a program that has previously been compiled, the prelinker notices that, too, and removes the assignment of the instantiation from the proper .ii file.
The .ii files should not, in general, require any manual intervention. The only exception is if the following conditions are met:
A definition is changed in such a way that some instantiation no longer compiles. (It generates errors.)
A specialization is simultaneously added in another file.
The first file is recompiled before the specialization file and is generating errors.
The .ii file for the file generating the errors must be deleted manually to allow the prelinker to regenerate it.
If the prelinker changes an instantiation assignment, it will issue a message, such as the following:
C++ prelinker: A<int>::f() assigned to file test.o C++ prelinker: executing: usr/lib/edg-prelink -c test.c |
The automatic instantiation scheme can coexist with partial explicit control of instantiation by the programmer, through the use of #pragma directives or command-line specification of the instantiation mode as described in the following subsections.
Instantiations are normally generated as part of the object file of the translation unit in which the instantiations are performed. But when 'one instantiation per object' mode is specified, each instantiation is placed in its own object file. One-instantiation-per-object mode is useful when generating libraries that need to include copies of the instances referenced from the library. If each instance is not placed in its own object file, it may be impossible to link the library with another library containing some of the same instances. Without this feature it is necessary to create each individual instantiation object file using the manual instantiation mechanism.
The automatic instantiation mode can be disabled by using the -no_prelink option.
If automatic instantiation is turned off, the following conditions are true:
The extra information about template entities that could be instantiated in a file is not put into the object file.
The .ii file is not updated with the command line.
The prelinker is not invoked.
Normally, when a file is compiled, no template entities are instantiated (except those assigned to the file by automatic instantiation). The overall instantiation mode can, however, be changed by a command line option.
You can use command-line options to control the instantiation behavior of the compiler. These options are divided into four sets of related options, as shown in the following list. You use one option from each category: options from the same category are not used together. For example, you cannot specify -ptnone in conjunction with -ptused.
-ptnone (the default), -ptused , or -ptall. (Automatic template instantiation should make the use of -ptused or -ptall unnecessary in most cases.)
-prelink (the default) or -no_prelink
-auto_include or -no_auto_include
-ptv
The following command line options control instantiation behavior of the compiler:
-ptnone | |||
None of the template entities are instantiated. If automatic instantiation is turned on (in other words, -prelink), any template entities that the prelinker instructs the compiler to instantiate are instantiated. | |||
-ptused | |||
Any template entities used in this compilation unit are instantiated. This includes all static members that have template definitions. If you specify -ptused, automatic instantiation is turned off by default. If you enable automatic instantiation explicitly (with -prelink), any additional template entities that the prelinker instructs the compiler to instantiate are also instantiated. | |||
-ptall | |||
Any template entities declared or referenced in the current compilation unit are instantiated. For each fully instantiated template class, all its member functions and static data members are instantiated whether or not they are used.
Nonmember template functions are instantiated even if the only reference was a declaration. If you specify -ptall, automatic instantiation is turned off by default. If you enable automatic instantiation explicitly (with -prelink), any additional template entities that the prelinker instructs the compiler to instantiate are also instantiated. | |||
-prelink | |||
Instructs the compiler to output information from the object file and an associated .ii file to help the prelinker determine which files should be responsible for instantiating the various template entities referenced in a set of object files. When -prelink is on, the compiler reads an associated .ii file to determine if any template entities should be instantiated. When -prelink is on and a link is being performed, the compiler calls a template prelinker. If the prelinker detects missing template entities, they are assigned to files (by updating the associated .ii file), and the prelinker recompiles the necessary source files. | |||
-no_prelink | |||
Disables automatic instantiation. Instructs the compiler to not read a .ii file to determine which template entities should be instantiated. The compiler will not store any information in the object file about which template entities could be instantiated. This option also directs the compiler to not invoke the template prelinker at link time. This is the default mode if -ptused or -ptall is specified. | |||
-auto_include | |||
Instructs the compiler to implicitly include template definition files if such definitions are needed. (See “Implicit Inclusion”.) | |||
-no_auto_include | |||
Disables implicit inclusion of template implementation files. | |||
-ptv | |||
Puts the template prelinker in verbose mode; when a template entity is assigned to a particular source file, the name of the template entity and source file is printed. |
![]() | Note: In the case where a single file is compiled and linked, the compiler uses the -ptused option to suppress automatic instantiation. |
This section provides you with typical combinations of command line instantiation options, along with an explanation of what these combinations do and how they may be used.
Although there are many possible combinations of options, the following are the most common combinations:
You can use #pragma directives to control the instantiation of individual or sets of template entities. There are three instantiation #pragma directives:
#pragma instantiate. See “#pragma instantiate”.
#pragma do_not_instantiate. See “#pragma can_instantiate”.
#pragma can_instantiate. See “#pragma can_instantiate”.
The #pragma instantiate directive causes a specific instance of a template declaration to be immediately instantiated.
The syntax of the #pragma instantiate directive is as follows:
#pragma instantiate entity |
The entity argument can be any of the following:
A template class name | |
A<int> | |
A member function name | |
A<int>::foo | |
A member function declaration | |
void A<int>::foo(int, char) | |
A static data member name | |
A<int>::name | |
A template function declaration | |
char* foo(int, float) |
The template definition of entity must be present in the compilation for an instantiation to occur. If you use #pragma instantiate to explicitly request the instantiation of a class or function for which no template definition is available, the compiler issues a warning.
The declaration needs to be a complete declaration of a function or a static data member, exactly as if you had specified it for a specialization of the template.
The argument to an instantiation #pragma directive cannot be a compiler-generated function, an inline function, or a pure virtual function.
A member function name (for example, A<int>::foo) can be used as an argument for a #pragma instantiate directive only if it refers to a single, user-defined member function that is not an overloaded function. Compiler-generated functions are not considered, so a name can refer to a user-defined constructor even if a compiler-generated copy constructor of the same name exists. Overloaded member functions can be instantiated by providing the complete member function declaration, as the following example shows:
char * A<int>::foo(int)) |
![]() | Note: Using the #pragma instantiate directive to instantiate a template class is equivalent to repeating the directive for each member function and static data member declared in the class. When instantiating an entire class, you can exclude a given member function or static data member by using the #pragma do_not_instantiate directive. |
The #pragma can_instantiate directive indicates that the specified entity can be instantiated in the current compilation, but need not be. It is used in conjunction with automatic instantiation to indicate potential sites for instantiation if the template entity is deemed to be required by the compiler.
The syntax of the #pragma can_instantiate directive is as follows:
#pragma can_instantiate entity |
The argument, entity, can be any of the following:
A template class name | |
A<int> | |
A member function name | |
A<int>::foo | |
A member function declaration | |
void A<int>::foo(int, char) | |
A static data member name | |
A<int>::name | |
A template function declaration | |
char* foo(int, float) |
The template definition of entity must be present in the compilation for an instantiation to occur. If you use #pragma can_instantiate to explicitly request the instantiation of a class or function for which no template definition is available, the compiler issues a warning.
The argument to a #pragma can_instantiate directive cannot be a compiler-generated function, an inline function, or a pure virtual function.
A member function name (for example, A<int>::foo) can be used as an argument for a #pragma can_instantiate directive only if it refers to a single, user-defined member function that is not an overloaded function. Compiler-generated functions are not considered, so a name can refer to a user-defined constructor even if a compiler-generated copy constructor of the same name exists. Overloaded member functions can be instantiated by providing the complete member function declaration, as shown in the following example:
char * A<int>::foo(int) |
The #pragma do_not_instantiate directive suppresses the instantiation of a specified entity. It is typically used to suppress the instantiation of an entity for which a specific definition is supplied.
The syntax of the #pragma do_not_instantiate directive is as follows:
#pragma do_not_instantiate entity |
The argument, entity, can be any of the following:
A template class name | |
A<int> | |
A member function name | |
A<int>::foo | |
A member function declaration | |
void A<int>::foo(int, char) | |
A static data member name | |
A<int>::name | |
A template function declaration | |
char* foo(int, float) |
The argument to a #pragma do_not_instantiate directive cannot be a compiler-generated function, an inline function, or a pure virtual function.
A member function name (for example, A<int>::foo) can be used as an argument for the #pragma do_not_instantiate directive only if it refers to a single, user-defined member function that is not overloaded. Compiler-generated functions are not considered, so a name can refer to a user-defined constructor even if a compiler-generated copy constructor of the same name exists. Overloaded member functions can be specified by providing the complete member function declaration, as the following example shows:
char * A<int>::foo(int) |
When implicit inclusion is enabled, the compiler assumes that if it needs a definition to instatiate a template entity declared in a .h file, it can implicitly include the corresponding .C file to get the source code for the definition. For example, if a template entity ABC::f is declared in file xyz.h, and an instantiation of ABC::f is required in a compilation but no definition of ABC::f appears in the source code processed by the compilation, the compiler looks to see if a file xyz.C exists, and if so it will process it as if it were included at the end of the main source file.
To find the template definition file for a given template entity the compiler needs to know the full path name of the file in which the template was declared and whether the file was included using the system include syntax (that is, #include <file.h>). This information is not available for preprocessed source containing #line directives. Therefore, the compiler does not attempt implicit inclusion for source code containing #line directives.
The definition-file suffixes that are tried are the following:
.c .C .cpp .CPP .cxx .CXX .cc .CC .c++ .C++ |
Implicit inclusion works well with automatic instantiation but the two are independent. They can be enabled or disabled independently, and implicit inclusion is still useful when automatic instantiation is not done.
Implicit inclusions are only performed during the normal compilation of a file (that is, not when doing only preprocessing). A common means of investigating certain kinds of problems is to produce a preprocessed source file that can be inspected. When using implicit inclusion it is sometimes desirable for the preprocessed source file to include any implicitly included files. This may be done using the -FE:generate_preprocessed_output command line option. This causes the preprocessed output to be generated as part of a normal compilation. When implicit inclusion is being used, the implicitly included files will appear as part of the preprocessed output in the precise location at which they were included in the compilation.