ILE C/C++ Programmer's Guide
When you use the TEMPINC instantiation management option, follow these
guidelines as you structure a program:
- If you have other declarations that are used inside templates but
are not template parameters, you must place or #include them in
either one of the included header files or in the tempinc file.
- Define any classes that are:
- Used in template arguments
- Required to generate the function template in the header file
- Note:
- If definitions require other header files, include them with the
#include directive. The definitions are then available when
the unit is compiled.
-
The function definitions in your template-implementation file can be explicit
specializations, template definitions, or both. Any explicit
specializations override the definitions generated by the template.
- If you specify a different directory for your tempinc files, ensure
that you specify it consistently for all compilations of your program,
including the bind step. For example:
CRTPGM PGM (MYLIB/MYPROG) MODULE(MYLIB/MYFILE)
- If you remove function instantiations or reorganize your program so that
the tempinc files become obsolete, delete one or more of these files and
recompile your program. If error messages are generated for a file in
the IFS TEMPINC directory, you delete the file and
recompile. To regenerate all of the tempinc files, delete the
TEMPINC directory, the modules, and recompile your program.
Notes:
- After the compiler creates an IFS TEMPINC directory or file, it
updates the file as each unit is compiled. The compiler never removes
information from an individual file.
- If you do not delete the modules, MAKEFILE rules prevent the modules from
being recompiled, and the IFS TEMPINC files cannot be updated with
all the lines needed for all the compilation units used in the program.
The bind fails.
- Do not put the definitions of any classes used in template
arguments in your source code.
- Note:
- This example shows what not to do:
Figure 322. Example of Class Definitions Used in Template Arguments Also Contained in Source Code (Does Not Compile Properly)
foo.h
template<class T> void foo(T*);
hoo.h
void hoo(A*);
foo.c
template<class T> void foo(T* t)
{t -> goo(); hoo(t);}
other.h
class A {public: void goo() {} };
main.cpp
#include "foo.h"
#include "other.h"
#include "hoo.h"
int main() { A a; foo(&a); }
This requires the expansion of the foo(T*) template with
class A as the template type parameter. The compiler creates
an IFS tempinc file TEMPINC\foo.cpp. The file
contents (simplified below) are:
#include "foo.h" //the template declaration header
#include "other.h" //file defining template type parameter
#include "foo.c" //corresponding template implementation
void foo(A*); //triggers template instantiation
- Note:
- This example cannot be properly compiled because the header file hoo.h
did not satisfy the conditions for inclusion but the header file is required
to compile the body of foo(A*).
|
One solution is to move the statement #include "foo.h" into the file foo.c.
In the Stack source, the file stack.c is a
template-implementation file. To create a program using the
Stack class template, both stack.h and
stack.c must reside in the same directory. You
include stack.h in any source files that use an instance of
the class. The stack.c file does not need to be
included in any source files. For example:
Figure 323. Example of Template-Implementation File
#include "stack.h"
void Swap(int i&, Stack<int,20>& s)
{
int j;
s >> j;
s << i;
i = j;
}
The compiler automatically generates the functions
Stack<int,20>::operator<<(int) and
Stack<int,20>::operator>>(int&).
|
Use the #pragma implementation directive to change the name of the
template-implementation file or place it in a different directory .
The syntax is:
>>-#pragma--implementation--"path"-----------------------------><
Notes:
- The path is used to specify the path name for the
template-implementation file. If it is only a partial path name, it
must be relative to the directory containing the header file.
- This path is a quoted string following the normal conventions for writing
string literals. Backslashes must be doubled.
To use the file stack.def as the template-implementation
file instead of stack.c, add the line: #pragma
implementation("stack.def") anywhere in the
stack.h file, in the Stack class. The
compiler then looks for the template-implementation file
stack.def in the same directory as
stack.h.
If you use the TEMPINC template instantiation management option, the
tempinc file is generated by the compiler.
- Note:
- Do not edit tempinc files.
Figure 324 shows a typical tempinc file generated by the
compiler.
Figure 324. A Typical tempinc File
1 /*0000000000*/ #pragma sourcedir("c:\swearsee\src")
2 /*0698421265*/ #include "\swearsee\src\list.h"
3 /*0000000000*/ #include "\swearsee\src\list.c"
4 /*0698414046*/ #include "\swearsee\src\mytype.h"
5 /*0698414046*/ #include "/QIBM/include/iostream.h"
6 template void List <MyType>::push(MyType);
7 template MyType List<MyType>::pop();
8 ostream& operator<<(ostream&,List<MyType>);
9 #pragma undeclared
10 int count(List<MyType>);
|
Notes:
- This pragma ensures that the compiler looks for nested include files in
the directory containing the original source file, as required by the ILE C++
file inclusion rules.
- The header file that corresponds to the tempinc file. The number in
comments at the start of each #include line (for this line
/*0698421265*/) is a time stamp for the included file. The
compiler uses this number to determine if the tempinc file is current or
should be recompiled. A time stamp containing only zeroes
(0) as in line 3 means the compiler is to ignore the
time stamp.
- The template-implementation file that corresponds to the header file in
line 2.
- Another header file that the compiler requires to compile the tempinc
file. All other header files that the compiler needs to compile the
tempinc file are inserted at this point.
- Another header file required by the compiler. It is referenced in
the function declaration in lines 6-7.
- The first statement of the explicit instantiation: In this case, the
class List<MyType> is to be defined.
- The second statement of the explicit instantiation: In this case,
the class List<MyType> member functions are to be
generated.
- The operator<< function is a nonmember function that
matched a template declaration in the list.h header
file. The compiler inserts this declaration to force the generation of
the function definition.
- The #pragma undeclared directive is used only by the compiler
and only in tempinc files. All function templates that are explicitly
declared in at least one compilation unit appear before this line. All
function templates that are called, but never declared, appear after this
line. This division is necessary because the C++ rules for function
overload resolution treat declared and undeclared function templates
differently.
- count is a function template that is called but not
declared. The template declaration of the function is contained in
list.h, but the instance count(List<MyType>)
is never declared.
[ Top of Page | Previous Page | Next Page | Table of Contents ]
(C) Copyright IBM Corporation 1992, 2005. All Rights Reserved.