There are 3 implementation schemes used by C++ compilers:
-
greedy instantiation, where the compiler generates an instantiation in each compilation unit that uses it, then the linker throws away all but one of them (this is not just a code-size optimization, it’s required so that function addresses,
static
variables, and the like are unique). This is the most common model. -
queried instantiation, where the compiler has a database of instantiations already done. When an instantiation is needed, the DB is checked and updated. The only compiler I know which uses this is Sun’s, and it isn’t used by default anymore.
-
iterated instantiation, where the instantiations are made by the linker (either directly or by assigning them to a compilation unit, which will then be recompiled). This is the model used by CFront — i.e. historically it was the first one used — and also by compilers using the EDG front-end (with some optimisations compared to CFront).
(See C++ Templates, The Complete Guide by David Vandevoorde and Nicolai Josuttis. Another online reference is http://www.bourguet.org/v2/cpplang/export.pdf, which is more concerned about the compilation model but still has descriptions of the instantiation mechanisms).