Next: , Previous: Using C++ standard library templates, Up: Templates


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.