Handout 16

Templates*


Using Templates

A C++ template is a framework for defining a set of classes or functions. The process of instantiation creates a particular class or function of the set by resolving the C++ template with a group of arguments that are themselves types or values. For example:

template <class T> class Array {
    T *data;
    int size;
public:
    T &operator[](int);
    /*  . . .  */
};

The code in this example declares a C++ class template named Array that has two data members named data and size and one subscript operator member function. Array<int> instantiates Array with type int . This instantiation generates the following class definition:

class Array {
    int *data;
    int size;
public:
    int &operator[](int);
    /*  . . .  */
};

Class Templates and Non-Type Parameters

1    #include <iostream.h>
2
3    template<class T, int length>
4    class Square
5    {
6    public:
7      void input(void) ;
8      void output(void) ;
9    private:
10     T array[length][length] ;
11   } ;
12
13   template<class T, int length>
14   void Square<T, length>::input(void)
15   {
16     int j, k ;
17
18     for (j = 0 ; j < length ; ++j)
19       for (k = 0 ; k < length ; ++k)
20         {
21      cout << "array[" << j << "][" << k << "] = " ;
22      cin >> array[j][k] ;
23         }
24   }
25
26   template<class T, int length>
27   void Square<T, length>::output(void)
28   {
29     int j, k ;
30
31     for (j = 0 ; j < length ; ++j)
32       for (k = 0 ; k < length ; ++k)
33         {
34      cout << array[j][k] ;
35      if (k < (length - 1)) cout << " " ; else cout << endl ;
36         }
37   }
38
39   int main()
40   {
41     Square<int,3> magic ;
42
43     magic.input() ;
44     magic.output() ;
45   }
46
Interaction with this program might appear on the screen as:
array[0][0] = 8
array[0][1] = 1
array[0][2] = 6
array[1][0] = 3
array[1][1] = 5
array[1][2] = 7
array[2][0] = 4
array[2][1] = 9
array[2][2] = 2
8 1 6
3 5 7
4 9 2

An Example Stack Class with Operator Overloading

1
2    template < class Item, int size >
3       class Stack{
4          public:
5
6             int operator << (Item& item); // Push operator
7             int operator >> (Item& item); // Pop operator
8
9             Stack() { top = 0; } // Constructor defined inline
10            ~Stack() {  } // Constructor defined inline
11
12         private:
13            Item stack[size]; // The stack of items
14            int top; // Index to top of stack
15   };
16
17   template <class Item, int size>
18   // The overloaded operator is used to push items to the stack. It returns
19   // an integer result: 1 = success, 0 = failure.
20        int Stack<Item, size>::operator << (Item & item) {
21        if (top >= size) return 0;
22        stack[top++] = item;
23        return 1;
24        }
25
26   template <class Item, int size>
27   // The overloaded operator is used to pop items from the stack. It returns
28   // an integer result: 1 = success, 0 = failure.
29        int Stack<Item, size>::operator >> (Item & item) {
30        if (top <= 0) return 0;
31        item = stack[--top];
32        return 1;
33        }
34
35
36   int main() {
37      Stack < int, 10 > A;
38      int x;
39
40      for(int i = 0; i < 10; i++) A << i; // push 'em on
41      for(int i = 0; i < 10; i++) A >> x; // pop 'em off
42   }

An Example from D&D

1    // Class template Stack
2    #ifndef TSTACK1_H
3    #define TSTACK1_H
4
5    #include <iostream.h>
6
7    template< class T >
8    class Stack {
9    public:
10      Stack( int = 10 );    // default constructor (stack size 10)
11      ~Stack() { delete [] stackPtr; } // destructor
12      bool push( const T& ); // push an element onto the stack
13      bool pop( T& );        // pop an element off the stack
14   private:
15      int size;             // # of elements in the stack
16      int top;              // location of the top element
17      T *stackPtr;          // pointer to the stack
18
19      bool isEmpty() const { return top == -1; }      // utility
20      bool isFull() const { return top == size - 1; } // functions
21   };
22
23   // Constructor with default size 10
24   template< class T >
25   Stack< T >::Stack( int s )
26   {
27      size = s > 0 ? s : 10;  
28      top = -1;               // Stack is initially empty
29      stackPtr = new T[ size ]; // allocate space for elements
30   }
31
32   // Push an element onto the stack
33   // return 1 if successful, 0 otherwise
34   template< class T >
35   bool Stack< T >::push( const T &pushValue )
36   {
37      if ( !isFull() ) {
38         stackPtr[ ++top ] = pushValue; // place item in Stack
39         return true;  // push successful
40      }
41      return false;     // push unsuccessful
42   }
43
44   // Pop an element off the stack
45   template< class T > 
46   bool Stack< T >::pop( T &popValue )
47   {
48      if ( !isEmpty() ) {
49         popValue = stackPtr[ top-- ];  // remove item from Stack
50         return true;  // pop successful
51      }
52      return false;     // pop unsuccessful
53   }
54
55   #endif
56
57   // Test driver for Stack template
58   #include <iostream.h>
59   #include "tstack1.h"
60
61   int main()
62   {
63      Stack< double > doubleStack( 5 );
64      double f = 1.1;
65      cout << "Pushing elements onto doubleStack\n";
66
67      while ( doubleStack.push( f ) ) { // success true returned
68         cout << f << ' ';
69         f += 1.1;
70      }
71
72      cout << "\nStack is full. Cannot push " << f
73           << "\n\nPopping elements from doubleStack\n";
74
75      while ( doubleStack.pop( f ) )  // success true returned
76         cout << f << ' ';
77
78      cout << "\nStack is empty. Cannot pop\n";
79
80      Stack< int > intStack;
81      int i = 1;
82      cout << "\nPushing elements onto intStack\n";
83
84      while ( intStack.push( i ) ) { // success true returned
85         cout << i << ' ';
86         ++i;
87      }
88
89      cout << "\nStack is full. Cannot push " << i 
90           << "\n\nPopping elements from intStack\n";
91
92      while ( intStack.pop( i ) )  // success true returned
93         cout << i << ' ';
94
95      cout << "\nStack is empty. Cannot pop\n";
96      return 0;
97   }


*Sources include this, this,this, this