Using Templates with g++
When using templated classes in a large, multi-file
program you'll need to explicitly instantiate templated
classes when using the g++ compiler. There are other options
using #pragma (that I haven't tried), but the method outlined
here is straightforward and works with all compilers (according
to the C++ standard, your mileage may vary).
Normally you use the pre-processor to #include appropriate header
files. For example, these import class declarations. You
then normally link in the corresponding class definition which
is traditionally in a matching .cc file (or .cpp, .cxx, etc.).
However, when a templated class is used, the implementation cannot be
a priori compiled since a different implementation is needed
for each instantiated template, e.g., Vector<int>
and
Vector<double>
each require a (slightly) different
implementation generated by the templated class definition. An easy
solution to this is to #include the source
code/implementation/definition of the templated class. This will work
fine unless you do this and instantiate a Vector<int> in
two separate files which are then linked --- the linker will complain
about multiple definitions of the same functions. (Intelligent linkers
might be the answer here, but as of yet ...).
The Template Instantiation File
To avoid the multiple definition problem, the implementation/definitions
are #included in a separate, per program template instantation
file. My convention is to use the name templatefoo.cc for
a project whose executable is named foo. Here's an example of
a template instantiation file for a word counting program (source is
accessible from class home page.)
#include "CPstring.h"
#include "uvmap.h"
#include "uvmap.cc"
#include "uviterator.h"
#include "uviterator.cc"
// instantiate base classes
template class Pair;
template class Map;
// instantiate unsorted vector implementation classes
template class UVMapIterator >;
template class UVMap;
// instantiate hash table implementation classes
#include "hmap.h"
#include "hmap.cc"
#include "hiterator.h"
#include "hiterator.cc"
template class HMap;
template class HMapIterator;
The key here is the separate instantation of each templated class
using the syntax:
template class ClassName;
Alternatives
It's possible to put all the code in the class declaration, in essence
making all member functions inline. Inline functions don't cause
conflicts with multiple definitions when linking. This is the solution
used in the Vector class since this class is used by beginning
students who shouldn't be burdened with the separate instantation file.
On some systems the compiler will generate warnings that the member
functions aren't actually inlined (some of them are large). When g++ is
used this isn't a problem since the warnings aren't generated when using
plain compiler flags (e.g., -g).