United States |
![]() |
![]() |
|
Previous | Contents | Index |
This section describes automatic instantiation in detail, beginning
with an overview of the instantiation process.
5.2.1 Overview of the Instantiation Process
The process of automatically instantiating a template has the following steps:
The following cxx command-line options are specific to automatic instantiation of templates:
-nopragma_template | Directs the compiler to ignore any #pragma define_template directives. This option is provided for users who want to quickly migrate to automatic instantiation without having to remove all the pragma directives from their code base. |
-nopt | Directs the compiler to not automatically instantiate templates. |
-pt | Directs the compiler to automatically instantiate templates. Each function template is placed in its own instantiation file, and member functions and static data members of each class template are grouped into one instantiation file. This option is the default. |
-ptr pathname |
Specifies a repository, with
./cxx_repository
as the default. If you specify several repositories, only the first is
writable, and the rest are read only.
Specifying this option at link time enables Compaq C++ to recognize and use the various template instantiations within the specified repository. If you use this option, make sure that the repository specified at compile time is the same one specified at link time. |
-pts | Directs Compaq C++ to automatically instantiate needed templates. Each member function or static data member is instantiated in its own separate file. |
-ptsuf" list" | Specifies a list of file name suffixes that are valid for template definition files. Items in the list must be separated by commas and each suffix preceded by a period. A suffix may have no more than eight characters excluding the beginning period. The default is ".cxx,.CXX,.C,.cc,.CC,.cpp,.c" . |
-ptv | Turns on verbose or verify mode to display each phase of instantiation as it occurs. This option is useful as a debugging aid; see Section 5.2.9.1.3. |
-use_ld_input |
Directs Compaq C++ to record the names of requested automatic
template instantiation object files in a linker options file in the
writable repository.
Compaq C++ then adds the linker options file to the ld command line using the -input file linker command line option. The default behavior is to add the instantiation file names directly to the ld command line. You can use the -use_ld_input option to reduce long ld command lines that cause linking to fail because of "Arg list too long" errors. |
Between distinct compilations and linking, Compaq C++ stores the necessary template instantiation information in a repository. You can specify a path name for the repository at both compile time and link time using the -ptr command-line option. If you specify multiple path names, the first becomes the writeable repository and the rest are designated as read-only repositories. A repository is implemented as a UNIX directory that can contain the following:
For example, given an instantiation request for the member function element(T) of template class Vector<int>, the repository would contain the following files:
File | Description |
---|---|
Vector__Ti.cmd | Dependency file containing the command-line options |
Vector__Ti.cxx | Instantiation source file |
Vector__Ti.o | Instantiation object file |
Vector__Ti.o.d | Dependency file containing the list of header files |
Vector__Ti.req | Instantiation request file |
The default repository acquires the same permissions as the directory
in which it resides, and therefore has the same access as the parent
directory. Any files created in the repository reflect this access.
5.2.4 Template Declaration File
This file contains the declaration of the template; include it in your application using the #include syntax.
The following is an example of a declaration file, AAA.h, containing a class template:
#ifndef AAA_H #define AAA_H template <class T> class AAA { T x; int y; public: void f(void); void g(T&); }; #endif |
The following is an example of a forward declaration for a function template:
template <class T> void sort (T*, int n); |
A template declaration file should include the header files it needs
for the types it uses. It should not include header files for types
used as template arguments or the definition of the template itself
because Compaq C++ handles these automatically.
5.2.5 Template Definition File
This file contains the template implementation. Given the previous declaration file example, AAA.h, the corresponding template definition file, AAA.cxx, would contain code fragments as follows:
template <class T> void AAA <T>::f(void) { /* ...*/ } . . . template <class T> void AAA <T>::g(T&) { /* ...*/ } |
Template definition files are treated like header files. They should contain only definitions of function, member function, or static data member templates. To avoid external linkages leading to unresolved symbols, Compaq C++ ignores any definitions of functions or data items found in template definition files.
If you include the corresponding declaration file in the template
definition file, or include the header files that declare any template
argument types, you should guard against multiple inclusion. If a
definition file does not exist for each corresponding declaration file,
you must write a name-mapping file to override the standard convention
(see Section 5.2.6). Otherwise, Compaq C++ does not include the
definition file in the instantiation source file.
5.2.6 Name-Mapping File
The name-mapping file is supplied by the user and must be named Template.map. The file is in the repository directory and contains information the compiler uses to automatically instantiate templates; it supplements template information found in the source code and in header files.
A name-mapping file consists of the following entries:
name
A simple name to identify the template to the compiler. Qualified names are unnecessary and not allowed. Parentheses, return types, and parameter lists are also not allowed.filename
The path name of the file containing the template definition. Each file listed will be included in the resulting instantiation source file.
Compaq C++ permits only one definition entry per template name. Thus, if the same name is used to define three different templates, each within its own file, you must list all three files in a single definition entry for that name.
Consider the following template function:
template <class T> void sort( T *p ) {} |
The following is a valid name-mapping file definition entry:
definition sort in "sort_impl.cxx"; |
With this definition, the compiler expects to find the body of function template sort() in the source file sort_impl.cxx.
Consider the following template member function:
template <class T> class List { public: void add_item(T new_item); /* ...*/ }; |
The following is a valid name-mapping file definition entry:
definition add_item in "List_funcs.cxx"; |
This definition instructs the compiler to find the body of the member function template add_item() in the source file List_funcs.cxx.
Presumably the source file List_funcs.cxx contains the following code:
#include "List.h" template <class T> void List<T>::add_item(T new_item){} |
Automatic instantiation makes including List.h more than once a possibility. To guard against this happening, you should enclose the code in include guards, as in the following example:
#ifndef List_H #define List_H ... // code for List.h #endif |
Consider the following overloaded template member function:
//List.h #ifndef List_H #define List_H template <class T> class List { Public: List(); List(const List& l); /* ...*/ }; #endif //List.cxx #include "List.h" template <class T> List<T>::List(){} //List_copy.cxx #include "List.h" template <class T> List<T>::List(const List& l){} |
The following is a valid name-mapping file definition entry:
definition List in "List.cxx", "List_copy.cxx"; |
By default, Compaq C++ creates one instantiation source file for each function template instantiation request, and one for each class template instantiation request. The instantiation source file includes all the headers needed to correctly instantiate a template. The order of inclusion is as follows (no file is included more than once):
For example, consider the following name-mapping file:
# Stack Implementation definition Stack in "Stack_Impl.cxx"; |
With an external unresolved symbol, Stack<C>::push(C), where class C is defined in the header file Cdef.h, the result would be the following instantiation source file:
#include "Cdef.h" #include "Stack.h" #include "Stack_Impl.cxx" typedef Stack<C> __dummy_; |
Compaq C++ matches each instantiation request with the corresponding template definition file to create the instantiation source file. The name of this source file must be similar to that of the template declaration file. Compaq C++ uses the following lookup order:
When a program makes a template instantiation request, Compaq C++ avoids creating and compiling a new instantiation source file if existing source and object files can be reused.
For each instantiation request, when Compaq C++ finds a corresponding instantiation source file or object file in the writeable repository, the following checks are performed:
When you build libraries and applications using manual instantiation, you face the tedious tasks of ensuring that all necessary templates are instantiated and of determining where each template instantiation is generated to avoid duplicates. The advantage of this method is that you have complete control over template instantiations; however using this approach can be time-consuming.
Automatic template instantiation performs these manual tasks for you if your build procedure and sources are properly set up. The procedure for building libraries and applications using automatic template instantiation differs somewhat from the procedure for manual instantiation. This section discusses the basic issues when using automatic template instantiation; it also provides suggestions and examples for resolving these issues.
See Section 3.4 for suggestions on organizing your sources.
5.2.9.1 Building a Standalone Library
Library vendors obviously need to provide a standalone library to their customers. With respect to templates, standalone means that the library contains:
In addition to library vendors, developers of large applications may want to divide their application into one or more standalone libraries to facilitate building. Creating a single library is straightforward. However, creating multiple libraries is more difficult if the libraries use the same template instantiations.
Previous | Next | Contents | Index |
|