Previous | Contents | Index |
A C++ template is a framework for defining a set of classes or functions. The process of instantiation creates a particular class or function of the set by resolving the C++ template with a group of arguments that are themselves types or values. For example:
template <class T> class Array { T *data; int size; public: T &operator[](int); /* ...*/ }; |
The code in this example declares a C++ class template named Array that has two data members named data and size and one subscript operator member function. Array<int> instantiates Array with type int. This instantiation generates the following class definition:
class Array { int *data; int size; public: int &operator[](int); /* ...*/ }; |
DEC C++ supports instantiation of C++ class, function, and static data member templates. The following sections describe the alternative methods available for instantiating templates.
Automatic Instantiation
This method instantiates templates automatically, as they are needed by your application. Special conventions must be followed regarding the name and location of template declaration and definition files. You can use a name mapping file to direct the compiler to the location of the template definition file. To get started quickly using automatic instantiation, see laz Section 5.1. For details, see Section 5.2.
Manual Instantiation
DEC C++ provides the following methods to manually instantiate templates:
By default, DEC C++ does not instantiate any template requests made by the application at compile time. Instead it creates instantiation source files in a repository. The repository is a directory where DEC C++ stores various information about the templates being instantiated. The files in the repository contain the source used to generate the requested instantiations. Consider the following example:
//main.cxx #include "Array.h" //template declaration file #include <String.hxx> //argument declaration file int main() { Array<String> v; v[0] = "hello world"; //request of Array's subscript //operator return 0; } |
The header file Array.h is referred to as the template declaration file. To organize a program to use automatic instantiation effectively, you must place the declarations of class and function templates into a header file. For more information, see Section 5.2.4.
The contents of Array.h are as follows:
template <class T> class Array { T *data; int size; public: T &operator[](int); }; |
The definitions or bodies of function and class member function templates should appear in a separate header file referred to as the template definition file. For more information regarding the contents of template definition files, see Section 5.2.5.
The template definition file should have the same base name as its corresponding template declaration file but with a different file extension. In the current example, the template definition file is named Array.cxx and is located in the same directory as Array.h. The contents of Array.cxx are as follows:
template <class T> T & Array<T>::operator[](int i) { return *(data + i); } |
For more details on template definition file lookup rules, see Section 5.2.7.1.
In the previous example of main.cxx, String is the type used to instantiate the class template Array. Declarations of various types that are used to instantiate a particular template must be defined within a header file. A compile-time diagnostic will be issued if DEC C++ compiles an instantiation whose argument type was defined in the source file instead of in a header file. For example:
//error.cxx #include "Array.h" struct MyString { /* ...*/ }; int main() { Array<MyString> v; v[0] = "Hello World"; return 0; } |
In this example, an error occurs because DEC C++ does not duplicate the definition of MyString in any instantiation source file created as a result of compiling the source file error.cxx.
Because DEC C++ performs automatic template instantiation by default, you do not need to specify the -pt option on the command line. To build the main program, use a cxx command such as the following:
cxx -I./include main.cxx |
This command assumes that main.cxx is located in the current directory and Array.h and Array.cxx are in the ./include subdirectory.
DEC C++ creates the default repository in ./cxx_repository. For more details about the contents of repositories, see Section 5.2.3.
One of the instantiation requests needed by the source file main.cxx is an instantiation of the Array's subscript member function, Array<T>::operator[](int), with type String. To satisfy this request, DEC C++ will generate the following instantiation source file in the default repository:
// Array__T6String.cxx #include "Array.h" //template declaration file #include <String.h> //argument declaration file #include "Array.cxx" //template definition file typedef Array<String> __dummy_; |
Once compilation of main.cxx completes, DEC C++ invokes a prelinker to determine the instantiation requests generated by the application. For each request, the prelinker reinvokes DEC C++ in a special template request mode to compile the necessary instantiation. The resulting object files are stored in a repository for use when DEC C++ links the application.
The following are some other helpful notes to get started quickly:
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 DEC 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 DEC 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 DEC C++ to record the names of requested automatic template
instantiation object files in a linker options file in the writable
repository.
DEC 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, DEC 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 |
Repository Permissions
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 DEC 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, DEC 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, DEC C++ does not include the definition file in the instantiation source file.
Previous | Next | Contents | Index |