sks wrote:
Hello all
Is the usage of extern keyword valid for telling the compiler to NOT
instantiate a template and to link it from an another binary?
No.
For example:
Suppose module A's binary contains a template class called "myTemplate", for
which there is an instantiation for 'int' type.
Now suppose a class in module B binary wants to use this template
instantiation, rather than "instantiate" its own, can I use "extern
template<int> class myTemplate;" syntax to use module A's instantiation?
There is no such syntax.
All you have to do is link your program together. B's use of the
template will generate unresolved references to various Template<int>
member functions. When you link A and B together, those will be
resolved by the instantiation contained in A.
You can prevent the compiler from instantiating Template<int> in module
B by not including the member function definitions in B's translation
unit.
There are two ways to deal with templates. Use a very smart C++
compiler that manages them for you. It maintains a template repository
module where it gathers up and instantiates all of the templates from
the entire program.
Then there is the way it's really done. You use a dumb C++ compiler
which doesn't know how to manage templates for your project (but which
generates templates automatically if it has access to their bodies).
You separate the declaration of the template class from its definition,
just like any other module.
Then in modules where you want the template instantiated, you #include
not just the definition, but the declaration, and write the
instantiation requests in those modules.
Elsewhere, in modules where you just want to use the templates but not
instantiate them, you #include the template class declarations only.
The compiler has no access to the definitions and so it doesn't try to
generate anything.
When I do this, I have some naming convention for the files. I make
both the definition and declaration .h files. One is something like
#include "template.h" and the other #include "template_body.h".
If you want to minimize recompilation dependencies, then what you can
do is make a separate module for each combination of template
parameters. Suppose we have a one-argument template called Template
that is to be instantiated over types A, B, C and D. You can make four
modules, one for each of these combinations. Template_A.cc will
#include the "Template_body.h" header and the "A.h" header that defines
class A, and then just contain the one instantiation request to make
Template<A>. Template_B.cc does the same thing for B and so on.
So now if you touch "Template.h" or "Template_body.h", all of these
template repository units have to be recompiled. But if you change
just A.h, then just Template_A.cc has to be recompiled: the other
templates don't have to be regenerated.
The worst-case scenario would be to have just one module which includes
all your templates, and all classes that those templates are
instantiated over, and puts all the instantiations together. It's easy
to add new material since everything is one place. But that thing has
to be compiled each time you touch any one of the class declarations.
Ouch!