10.4. Template instantiation file method

The template instantiation file method on AIX basically means letting the compiler decide which template code to instantiate as a final step in the compile and link process. This solves the long compile time disadvantage of the simple template code layout method because the compiler need only compile each template instance once.

This method requires that the declaration and definition of the template are kept in separate files. This is because only the template declaration must be included in every compilation unit that uses the template. If the definition of the template were also in the header file, it would also be included in the source file, and thus compiled, resulting in a situation similar to that in the simple method.

This template model can also benefit from the use of the -qfuncsect compiler option, since it means the linker can discard code sections that are not referenced in the final executable.

The template declaration should be left in the header file, as in the simple template method. The definition of the template member functions needs to be in a file with the same basename as the header file but with a .c (lower case C) file name extension.

Note

By default, the file containing the template definition code must have the same name as the template declaration header file, but with a file name extension of .c (lowercase c), even though this extension normally indicates a C language source file. It must also exist in the same directory as the template declaration header file. If the template definition file is not in the same directory, has a different basename, or has a different file name extension (such as .C, .cxx, or .cpp, which are normally used for C++ source files), then the compiler will not detect the presence of the template code to be used with the template declaration header file.


Using the stack template example introduced earlier, the template declaration shown in Example 10-1 on page 379 would be in the stack.h file, while the template definition code shown in Example 10-2 on page 380 would be in the stack.c file in the same directory. If the template definition code file was named stack.cxx or stack_code.c, then the compiler will not associate the file with the template declaration in the stack.h header file.

The name of the template definition file can be changed, if desired, using the implementation pragma directive as follows:

#pragma implementation(string-literal)

where string-literal is the path name for the template definition file enclosed in double quotes. For example, if the stack template definition code were to be stored in the stack_code.cxx file, then the stack.h header file would have the following directive:

#pragma implementation("stack_code.cxx")

Once the structure of the source code has been altered to conform to the required layout, the templates can be used with this method.

10.4.1. The -qtempinc option

The -qtempinc option is used when compiling source code that instantiates templates. When no directory is specified with the option, the compiler will create a directory called tempinc in the current directory. For example:

$ xlC main.C -qtempinc

The user may optionally specify the name of a directory to use for storing the information on the templates to be generated. This allows the same tempinc directory to be used when creating an executable that consists of object files that are compiled in different directories. For example:

$ xlC -c file1.C file2.C -qtempinc=../app1/templates
$ cd ../app1
$ xlC -o app1 main.C ../src/file1.o ../src/file2.o -qtempinc=./templates

The tempinc directory is used to store information about the templates that are required to be generated. When invoked with the -qtempinc option, the compiler collects information about template instantiations and stores the information in the tempinc directory. As the last step of the compilation before linking, the compiler generates the code for the required template instantiations. It then compiles the code and includes it with the other object files and libraries that are passed to the linker to create the final executable.

If the compiler detects a code layout structure that enables the tempinc method to be used, it will automatically enable the -qtempinc option, even if it was not specified on the command line. This causes the template instantiation information to be stored in the tempinc directory. If you want to specify a different directory, you should explicitly use the -qtempinc=dir_name option on the command line. If you want to prevent the compiler from automatically generating the template information, which may be the case when creating a shared object, then use the -qnotempinc option. See 11.2, “Shared objects with templates” on page 402 for more information on the use of the -qnotempinc option when creating shared objects.

One important point to note about the -qtempinc option is that you should use the same value when compiling all compilation units that will be linked together. In other words, do not compile half of the application with -qtempinc, and the other half with -qtempinc=dir_name. Only one tempinc directory can be specified on the final C++ command line that is used to link the application, which means that half of the template instance information will be missing. If more than one tempinc option is specified on the command line, the last one encountered will prevail.

10.4.2. Contents of the tempinc directory

The compiler generates a file in the tempinc directory for each template header file that has templates instantiated. The file has the same name as the header file, but with a .C (uppercase C) file name extension. The compiler generates the file when it detects the first instantiation of a template that is declared in the header file with the same name. Information on the subsequent instances of the template is added to the file.

As the final step of the compilation before linking, the compiler compiles all of the files in the tempinc directory and passes the object files to the linker along with the user specified files.

The contents of a template information file are shown in Example 10-3.

Example 10-3. A sample template information file[1]
1: /*0965095125*/#include "/redbooks/examples/C++/stack.h"
2: /*0000000000*/#include "/redbooks/examples/C++/stack_code.cxx"
3: template stack<int>::stack(int);
4: template stack<int>::~stack();
5: template void stack<int>::push(int);
6: template int stack<int>::pop();

[1] The line number at the beginning of each line is added intentionally for explanation. These numbers and the colon characters “:” are not part of the file.

The code on line 1 includes the header file that declares the template. The comment at the start of the line is a time stamp and is used by the compiler to determine if the header file has changed, which would require the template instance information file to be recompiled.

The code on line 2 includes the template implementation file that corresponds to the header file in line 1. A time stamp consisting of all zeros indicates that the compiler should ignore the time stamp. The file may include other header files that define the classes that are used in template instantiations. For example, if there was a user defined class Box, and the compiler detected an instantiation of stack<Box>, then the header file that defines the class Box would be included in the instance information file.

The subsequent lines in the example shown above cause the individual member functions to be instantiated.

10.4.3. Forcing template instantiation

You can, if you wish, structure your program so that it does not use automatic template instantiation. In order to do this, you must know which template classes and functions need to be instantiated.

The #pragma define directive is used to force the instantiation of a template, even if no reference is made to an instance of the generated template. For example:

#pragma define(stack<double>);

This, however, means that the template implementation file needs to be included in the compilation units that have the #pragma define directives, which results in the same disadvantages of the simple template method described in 10.3, “Simple code layout method” on page 381.

An alternative to this is to manually emulate the process used by the compiler to automatically create the appropriate template instances. Using the stack class as an example, the following compilation unit shown in Example 10-4 could be used to force the creation of the desired stack template classes, even though no objects of those types are referenced in the source code.

Example 10-4. A sample usage of #pragma define[2]
1: #include "/redbooks/examples/C++/stack.h"
2: #include "/redbooks/examples/C++/stack_code.cxx"
3: #include "/redbooks/examples/C++/Box.h"         // definition of class Box
4: #pragma define(stack<int>);
5: #pragma define(stack<Box>);
6: #pragma define(stack<char>);
7: #pragma define(stack<short>);

[2] The line number at the beginning of each line is added intentionally for explanation. These numbers and the colon characters “:” are not part of the file.

This type of method will be useful when creating shared objects with the makeC++SharedLib command. Users of the VisualAge C++ for AIX product should use the -qmkshrobj option instead. See 11.2, “Shared objects with templates” on page 402 for more information.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset