DEC C++
Using DEC C++ for DIGITAL UNIX Systems


Previous Contents Index


Chapter 5
Using Templates

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:

5.1 Automatic Instantiation Quick Start

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:

5.2 Automatic Instantiation Specifics

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:

  1. The user issues a cxx command to compile or link specified files.
    If the user invokes the cxx command specifying no source files but only object, archive, or shared library files, the process skips ahead to step 5. Remember that if you explicitly specified the repository path name during compilation, you must also specify the repository path name on the cxx command at link time.
  2. DEC C++ sets the current repository. If the user specifies the -ptr option and the specified repository does not exist, DEC C++ creates the user-specified repository. Otherwise, DEC C++ checks for the existence of a repository named ./cxx_repository. If ./cxx_repository does not exist, DEC C++ creates one in your current working directory.
  3. DEC C++ invokes the compiler in default mode. The compiler uses the template declaration file, the template definition file, and the top-level header files of your application to create an instantiation source file for each function template or class template used within the source program. If you use the -pts switch, a separate instantiation source file is created for each member function template or static data member template used within the source program.
    If an instantiation source file already exists in the repository, the compiler checks whether this file is current with regard to the corresponding header files and the command-line options. If the instantiation source file is out of date, the compiler re-creates it.
  4. If you specified the -c option on the command line, DEC C++ has completed the compilation and returns control to the user.
  5. DEC C++ invokes ld to perform a prelink, to partially link those object files that are generated from the C++ or C source files specified on the command line, plus any archived or shared library files. The linker performs symbol processing only; it does not create an executable.
  6. For each unresolved symbol reported by the linker in step 5, DEC C++ searches either the default or the user-specified repositories for the corresponding instantiation object file. The writeable repository is searched first, followed by any read-only repositories specified on the cxx command.
  7. For each instantiation object file found in the writeable repository, DEC C++ checks whether that file is up to date with regard to the instantiation source file. For class templates, DEC C++ also checks the contents of the instantiation request file to see whether it specifies all the members that have been requested thus far during the prelink phase. If the instantiation object file is found to be out of date or the instantiation request file is missing any requests, DEC C++ invokes the compiler in template request mode to generate the instantiation. In template request mode, the compiler generates code only for the function template or class template members specified in the instantiation request file. The resulting object file is placed in the writeable repository and added to the link command in step 5. If the instantiation object file is up to date, DEC C++ simply adds the file to the link command in step 5.
    For each instantiation object file found in a read-only repository, DEC C++ performs no dependency checking except for class templates: DEC C++ verifies that the instantiation request file specifies all the members that have been requested thus far during the prelink phase. If the instantiation request file is missing any requests, DEC C++ ignores the object file. Otherwise DEC C++ adds the object file to the link command in step 5.
    If no instantiation object file is found, or if a read-only repository object was found but is missing requests, DEC C++ creates an instantiation object file by compiling (in template request mode) the instantiation source file located in the writeable repository. The resulting object is placed in the writeable repository and added to the link command in step 5.
  8. DEC C++ repeats steps 5 through 7 until either no unresolved symbols remain or no object files can be found within the repositories that correspond to the unresolved symbols.
  9. DEC C++ invokes ld with the modified link command to perform the final link.

5.2.2 Command-Line Options Specific to Templates

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.

5.2.3 Repositories

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