7.4.2 Providing your own templates
In addition to the template classes provided by the C++ standard library
you can define your own templates. The recommended way to use templates
with g++
is to follow the inclusion compilation model,
where template definitions are placed in header files. This is the
method used by the C++ standard library supplied with GCC itself. The
header files can then be included with '#include' in each source
file where they are needed.
For example, the following template file creates a simple
Buffer<T>
class which represents a circular buffer holding
objects of type T
.
#ifndef BUFFER_H
#define BUFFER_H
template <class T>
class Buffer
{
public:
Buffer (unsigned int n);
void insert (const T & x);
T get (unsigned int k) const;
private:
unsigned int i;
unsigned int size;
T *pT;
};
template <class T>
Buffer<T>::Buffer (unsigned int n)
{
i = 0;
size = n;
pT = new T[n];
};
template <class T>
void
Buffer<T>::insert (const T & x)
{
i = (i + 1) % size;
pT[i] = x;
};
template <class T>
T
Buffer<T>::get (unsigned int k) const
{
return pT[(i + (size - k)) % size];
};
#endif /* BUFFER_H */
The file contains both the declaration of the class and the definitions
of the member functions. This class is only given for demonstration
purposes and should not be considered an example of good programming.
Note the use of include guards, which test for the presence of the
macro BUFFER_H
, ensuring that the definitions in the header
file are only parsed once if the file is included multiple times in the
same context.
The program below uses the templated Buffer
class to create a
buffer of size 10, storing the floating point values 0.25 and
1.0 in the buffer:
#include <iostream>
#include "buffer.h"
using namespace std;
int
main ()
{
Buffer<float> f(10);
f.insert (0.25);
f.insert (1.0 + f.get(0));
cout << "stored value = " << f.get(0) << '\n';
return 0;
}
The definitions for the template class and its functions are included in
the source file for the program with '#include "buffer.h"' before
they are used. The program can then be compiled using the following
command line:
$ g++ -Wall tprog.cc
$ ./a.out
stored value = 1.25
At the points where the template functions are used in the source file,
g++
compiles the appropriate definition from the header file and
places the compiled function in the corresponding object file.
If a template function is used several times in a program it will be
stored in more than one object file. The GNU Linker ensures that only
one copy is placed in the final executable. Other linkers may report
"multiply defined symbol" errors when they encounter more than
one copy of a template function--a method of working with these linkers
is described below.