Why No Recompile Using Implicit C++ Templates?
Many C++ compilers support two ways to organize template declaration and
definition files, definitions-included and definitions-separate.
In definitions-included organization, template definitions are
explicitly provided to the compiler, typically by #include'ing the
definitions file at the bottom of the template declarations header
file. In the definitions-separate approach, template definitions are
not explicitly provided to the compiler, and the compiler is given
permission to go looking for a file containing the needed definitions,
typically by searching the #include path for a file with the same
basename as the template declaration file, and a file extension of .c,
.C, .cpp, .cc, or .cpp.
The definitions-separate approach leads to a problem when used in
combination with nmake and C++ compilation systems which perform
compile-time instantiation. Since the nmake scanning rules rely
upon #include statements to infer implicit file prerequisites, under
definitions-separate organization, template declaration files will not
be inferred as an implicit prerequisites of a primary object, and
updating a template definition will not cause rebuilding of any
dependent template instantiations.
Here is an example, using the Sun 4.2 C++ compiler
definitions-separate feature. Note that nmake fails to
recompile/reinstantiate when the implicitly-included template
definitions file is touched.
$ cat Makefile
CC = CC
myprog :: myprog.C
$ cat myprog.C
#include <iostream.h>
#include "mytemplate.h"
int
main()
{
mytemplate<5> myt;
cout << myt.get_x() << endl;
return 0;
}
$ cat mytemplate.h
#ifndef MYTEMPLATE_H
#define MYTEMPLATE_H
template <int T> class mytemplate {
public:
mytemplate();
int get_x();
private:
int x;
};
#endif
$ cat mytemplate.C
template <int T>
mytemplate<T>::mytemplate()
: x(T)
{
}
template <class T>
int
mytemplate<T>::get_x()
{
return x;
}
$ nmake
+ ppcc -i -l /tools/nmake/sparc5/v3.1.2/lib/cpp CC -O -I-D/tools/nmake/
sparc5/v3.1.2/lib/probe/C/pp/58D7E9152binCC -I. -I- -c myprog.C
+ ppcc -i -l /tools/nmake/sparc5/v3.1.2/lib/cpp CC -O -I-D/tools/nmake/
sparc5/v3.1.2/lib/probe/C/pp/58D7E9152binCC -I. -I- -I. -o myprog mypro
g.o
$ touch mytemplate.h
$ sleep 1
$ nmake
+ ppcc -i -l /tools/nmake/sparc5/v3.1.2/lib/cpp CC -O -I-D/tools/nmake/
sparc5/v3.1.2/lib/probe/C/pp/58D7E9152binCC -I. -I- -c myprog.C
+ ppcc -i -l /tools/nmake/sparc5/v3.1.2/lib/cpp CC -O -I-D/tools/nmake/
sparc5/v3.1.2/lib/probe/C/pp/58D7E9152binCC -I. -I- -I. -o myprog mypro
g.o
$ touch mytemplate.C
$ sleep 1
$ nmake
To get the desired behaviour, it is necessary to explicitly #include the
definitions file in the template .h file. To ensure that you don't
inadvertently leave out the definitions file #include and possibly
trigger implicit inclusion, you may wish to rename the definitions
file so it no longer has the same basename as the corresponding .h file:
$ cat mytemplate.h
#ifndef MYTEMPLATE_H
#define MYTEMPLATE_H
template <int T> class mytemplate {
public:
mytemplate();
int get_x();
private:
int x;
};
#include "mytemplateDEF.C"
#endif
Last Update: Wednesday,20-Dec-06 13:21:58 CST
|