6.2 Template Parameters


A template class makes implicit assumptions about the type with which it is instantiated. These assumptions are based on the operations that the template class applies to the objects of the parameterizing type. These assumptions are implicit because they are not visibly represented in the declaration of the template class. Rather, the assumptions must be inferred by examining the code of the template class.

The Queue template class contains three assumptions about the QueueItem template parameter. First, the code:

   template <class QueueItem> class Queue {
   private:
      QueueItem buffer[100];
   ...
   };
assumes that QueueItem has a default constructor (i.e., a constructor that takes no arguments). A default constructor is needed in order to declare and array of a given type. Classes like Location, Shape, and Frame that have default constructors can be used to elaborate the Queue template. However, an error message will result from:
	Queue<Message>  QueueOfMessages;

   	Queue<Clock>    QueueOfClocks;
     
because these classes do not have default constructors. Second, the code:
  template <class QueueItem> 
      void Queue<QueueItem>::Insert(QueueItem item) {
             ...
             buffer[tail] = item;
             ...
       }
assumes that the QueueItem class has an appropriately defined assignment operator. All classes have a default assignment operator - a bit-wise copy. In simple classes this is an appropriate assignment operator. For example, in the case of Queue<int> and Queue<Location> the default assignment operator is appropriate. However, the default assignment operator may not be appropriate for a class that contains pointers as private data. Third, the code:
  template <class QueueItem> 
      QueueItem Queue<QueueItem>::Remove() {
            ...
            return buffer[val];
      }
returns a copy of the object that is in the internal buffer. This code assumes that an appropriate copy constructor is defined for the class being substituted for QueueItem.

Other templates make more demanding assumptions about the class or type used to instantiate the template. Consider the following template declaration:

   template <class T> class Displayable {
     private:
       T*       displayed;
       TextBox* textBox;
     public:
       Displayable(TextBox* tbox);        // testbox to show in
       void ShowThis(T* d);		  // what to show
       void Show();                       // show current value
       void Reset();			  // reset displayed from textBox
       ~Displayable();
   };

This template is designed to point to a TextBox in which a current value will be displayed and from which a new value can be read. The template also contains a pointer ("displayed") to an object of the template's parameter type. To achieve its intent, the template must make assumptions about how the value can be obtained from the displayed object and how a new value can be given to the displayed object. Since the type of the displayed object is now know (its type is the template's parameter), the template code must make assumptions about (impose constraints on) the type that is used to instantiate the template. The code for the Displayable template is as follows:

   template <class T> 
      Displayable<T>::Displayable(TextBox *tbox)
         {textBox = tbox;  displayed = (T*)0;}

   template <class T> 
      Displayable<T>::ShowThis(T* d) { displayed = d; }

   template <class T> 
      Displayable<T>::Show() { textBox->SetText(displayed->ToString()); }

   template <class T> 
      Displayable<T>::Reset() { displayed->FromString(textBox->GetText()); }

   template <class T> 
      Displayable<T>::~Displayable(){}
   
   
The Displayable template assumes that the instantiating type has two methods: Any type that satisfies these two assumptions may be used to instantiate the Displayable template. Any type or class not having both of these methods cannot be used to instantiate the template. For example, it is not possible to have Displayable or Displyable or Displayable because all of these lack the required methods ToString and FromString.

Exercises

  1. Write a class named Integer that holds a value of type int. This class should have the ToString and FromString methods defined for it. Write a test program that uses this class to instantiate the Displayable template and display an integer in the TextBox.

  2. Write a class named Real that holds a value of type float. This class should have the ToString and FromString methods defined for it. Write a test program that uses this class to instantiate the Displayable template and display a float value in the TextBox.

Last Updated: October 26, 1995 / kafura@cs.vt.edu