Compiling Templates


The purpose of this assignment is to learn even more about C++.  Specifically, how to managed the files for class templates.


Classes, but not Templates

Go back and review Lab 7. In that lab assignment we saw that it is possible to put some code in one file and other code in a second file, then compile the two C++ files separately.

The following is an example of creating a class for an integer stack. The class definitions can go in a file named "stack.h", and the class' member functions can go in a seperate file named "stack.cpp". In short, one file contains the definition and another file contains the implementation.

With these files divided we can compile stack.cpp into an object code file just once.  Later, that single .o file can be linked with one or more applications that need an integer stack.  For example, if bob.cpp needs an integer stack, bob could just #include stack.h and then link to stack.o without re-compiling stack.cpp.

     stack.h

class IntegerStack
{
   public:
     IntegerStack();
     int IsEmpty();
     int IsFull();
     void Push (int value);
     int Pop();
   private:
     int top;
     int items[100];
};
     stack.cpp

#include "stack.h"

IntegerStack::IntegerStack()
{ top = -1; }

int IntegerStack::IsEmpty()
{ return (top == -1); }

int IntegerStack::IsFull()
{ return (top == 100); }

void IntegerStack::Push(int value)
{ top++; items[top] = value; }

int IntegerStack::Pop()
{ return items[top--]; }

Here is a main() to test that integer stack. This main() reads an integer, breaks the integer into individual digits, then prints the digits one per line.
     stack_test.cpp

#include <iostream>
using namespace std;

#include "stack.h"

int main()
{
   IntegerStack mystack;  // the stack
   int number;            // user input

   // get a number
   cout << "Enter an integer : ";
   cin >> number;

   // put the digits of the number on the stack
   while (number > 0)
     {
      if (!mystack.IsFull())
        {
         mystack.Push(number%10);
         number = number / 10;
        }
      else
         cout << "Stack Overflow!!!\n";
     }

   // print the contents of the stack
   cout << "That number printed vertically is\n";
   while (!mystack.IsEmpty())
     cout << mystack.Pop() << endl;
   cout << endl << endl;
}

It is very important to note, that we can change this test program file over and over and never need to recompile the stack.cpp file.


Classes with Templates

Compiling class templates is different. For the compiler to compile a class template, it needs to know how the template will be instantiated. The object code for a stack of integers looks different than the object code for a stack of floats. So, the compiler can not compile the generic stack template code until it knows what type of stack of create.

For example, the following will not work. We cannot compile the following stack.cpp without knowing what <ItemType> will be.
     stack.h

template <class ItemType>
class StackType
{
   public:
     StackType();
     bool IsEmpty();
     bool IsFull();
     void Push (ItemType value);
     ItemType Pop();
   private:
     int top;
     ItemType items[10];
};

     stack.cpp

template <class ItemType>
StackType<ItemType>::StackType()
{ top = -1; }

template <class ItemType>
bool StackType<ItemType>::IsEmpty()
{ return (top == -1); }

template <class ItemType>
bool StackType<ItemType>::IsFull()
{ return (top == 100); }

template <class ItemType>
void StackType<ItemType>::Push(ItemType value)
{ top++; items[top] = value; }

template <class ItemType>
ItemType StackType<ItemType>::Pop()
{ return items[top--]; }


There are very few solutions to this problem. One solution is put both the class definition and the class' member functions into the same file (using named .h), and then have the client include this one single file.


Assignment

The following stack_template.h file creates a template for a small stack. The stack_test.cpp file uses that template.

I made two minor changes to stack_test.cpp so that it will not work. Your assignment is to fix the stack_test.cpp file. Hint: I just deleted two lines. Turn in a corrected version of stack_test.cpp.

     stack_template.h

/*** Class Definition ***********/
template <class ItemType>
class StackType
{
   public:
      StackType();
      bool IsEmpty();
      bool IsFull();
      void Push (ItemType value);
      ItemType Pop();
   private:
      int top;
      ItemType items[10];
};

/*** Function Definitions *******/

template <class ItemType>
StackType<ItemType>::StackType()
{ top = -1; }

template <class ItemType>
bool StackType<ItemType>::IsEmpty()
{ return (top == -1); }

template <class ItemType>
bool StackType<ItemType>::IsFull()
{ return (top == 100); }

template <class ItemType>
void StackType<ItemType>::Push(ItemType value)
{ top++; items[top] = value; }

template <class ItemType>
ItemType StackType<ItemType>::Pop()
{ return items[top--]; }

     stack_test.cpp

#include <iostream>
using namespace std;


int main()
{
              // the integer stack
int number;   // user input

// get a number
cout << "Enter an integer : ";
cin >> number;

// put the digits of the number on the stack
while (number > 0)
  {
   if (!mystack.IsFull())
     {
      mystack.Push(number%10);
      number = number / 10;
     }
   else
      cout << "Stack Overflow!!!\n";
  }

// print the contents of the stack
cout << "That number printed vertically is\n";
while (!mystack.IsEmpty())
   cout << mystack.Pop() << endl;
cout << endl << endl;
}