## CS 596 OODP Template Classess

[To Lecture Notes Index]
San Diego State University -- This page last updated November 16, 1995

## Reference

Chapter 7 of Lippman's text

## Class Templates

```
#include <iostream.h>

template <class Whatever>
class BankAccount
{
public :
Whatever balance;
BankAccount(Whatever amount = 0.0);
};

template <class Whatever>
BankAccount<Whatever>::BankAccount(Whatever amount)
{
balance = amount;
}

class Yen {
public:
Yen ( float StartAmount = 0) {amount = StartAmount ;};
Yen operator +( const Yen& AddMe ) {
return Yen( amount + AddMe.amount ); }
friend ostream&  operator<<(ostream& , const
Yen&);
private:
float amount ;
};

ostream&  operator<<(ostream& out, const Yen& money)
{
out << "Yen: " << money.amount;
};

main()
{
BankAccount<int> me(10);
BankAccount<Yen> you(200.0);
cout << me.balance << you.balance;
}
```

Implicit Type Assumptions
```#include <iostream.h>

template <class Whatever>
class BankAccount
{
public :
Whatever balance;
BankAccount(Whatever amount = 0.0);
};

template <class Whatever>
BankAccount<Whatever>::BankAccount(Whatever amount)
{
balance = amount;
}

class Yen {
public:
Yen ( float StartAmount = 0) {amount = StartAmount ;};
Yen operator +( const Yen& AddMe ) {
return Yen( amount + AddMe.amount ); }
private:
float amount ;
};

main(){
BankAccount<int> me(10);
cout << me.balance;		// Compiles
}
main()
{
BankAccount<Yen> me(10);
cout << me.balance ;		// Does not compile
}
```

Multiple Parameters
```template <class TypeA, class TypeB>
class Foo
{
public :
TypeA balance;
TypeB amount;

TypeB	bar( TypeA in );
};

template <class TypeA, class TypeB>
TypeB Foo<TypeA, TypeB> :: bar( TypeA in )
{
balance = in;
return amount;
}

```

### Instantiation

```#include <iostream.h>
```
```template <class Whatever>
class BankAccount
{
public :
Whatever balance;
static int test;

BankAccount(Whatever amount = 0.0);
};

template <class Whatever>
BankAccount<Whatever>::BankAccount(Whatever amount)
{
balance = amount;
test = amount;
}
```
```template <class Whatever> BankAccount<Whatever> :: test = 0;

main(){
BankAccount<int> me(10);
BankAccount<float> you(20);
BankAccount<int> them(30);

cout << me.test << endl;
cout << you.test << endl;
cout << them.test << endl;
}
```
Output ( CC )
```30
20
30
```

Special Instances of Operations
```#include <iostream.h>
#include <string.h>

template <class Type>  class Special  {
public :
Type dataMember;
void setData( Type input );
friend ostream& operator << ( ostream&,
Special< Type >& );
};

template <class Type>  void Special<Type>::setData( Type input ) {
cout << "In set data" << endl;
dataMember = input;
}

void Special<char*>::setData( char* input ) {
cout << "In char set data" << endl;
dataMember = new char[strlen(input)];
strcpy(dataMember,input);
}

template <class T >
ostream& operator << ( ostream& output, Special< T
>& object) {
output << object.dataMember;
return output;
}

main(){
Special<int> normal;		Special<char*> special;
normal.setData(5);
special.setData("Hi Mom");
cout << "normal " << normal << " special " <<
special << endl;
}
```
Output
```In set data
In char set data
normal 5 special Hi Mom
```

Non-Type Template Types
```#include <iostream.h>

template <int Size>
class Board
{
public :
int Squares[Size];
};

main(){
Board<100> large;		// OK

const int y = 8;
Board<y> normal;		// OK

int x = 10;
Board<x> normal;		// Does not compile,  needs constant
}
```

Templates and Inheritance
Template Base and Derived Classes
```#include <iostream.h>
template <class Type>
class Top {
public:
Type data;
Top( Type value ) {
data = value;
cout << "Top Construct\n";
};

void setData( Type value) {
data = value;
cout << "In top\n";
};
};

template <class Type>
class Bottom : public Top<Type>{
public:
Bottom( Type value ) : Top<Type>( value) {
cout << "Bottom Construct\n";};

void setNewData( Type value) {
data = value;cout << "In Bottom\n";};
};

main ()
{
Top<int> A( 1);
Bottom<float> B( 3.3);
B.setData( 5.5);
}
```

Templates and Inheritance
Regular Base and Template Derived Class
```
class Top {
public:
int data;
Top( int value ) {
data = value;
cout << "Top Construct\n";
};

void setData( int value) {
data = value;
cout << "In top\n";};
};

template <class Type>
class Bottom : public Top   {
public:
Type NewData;

Bottom( int A, Type value ) : Top(A) {
cout << "Bottom Construct\n";
NewData = value;};

void setNewData( Type value) {
NewData = value;
cout << "In Bottom\n";};
};

main ()
{
Top A( 1);
Bottom<float> B(2, 3.3);
B.setData(  55);
```

}Templates and Inheritance
Template Base and Regular Derived Class
```
template <class Type>
class Top {
public:
Type data;
Top( Type value ) {
data = value;
cout << "Top Construct\n";
};

void setData( Type value) {
data = value;
cout << "In top\n"; };
};

class Bottom : public Top<int>   {
public:
float NewData;

Bottom( int A, float value ) : Top<int> (A) {
cout << "Bottom Construct\n";
NewData = value;};

void setNewData( float value) {
NewData = value;
cout << "In Bottom\n";};
};

main ()
{
Top<char> A( 1);
Bottom B(2, 3.3);
B.setData(  55);
}
```

Finally A Usable Stack
```
#ifndef	_Stack_HH
#define	_Stack_HH

#include <iostream.h>
#include <assert.h>

class Stack
{
friend ostream&  operator<<(ostream& , Stack&);

public:
Stack(int StartSize = 10);
Stack(const Stack&);

Stack& operator=(const Stack&);

~Stack();

int isEmpty() 	const;
int isFull()	const;
void push(const T& item);		// Note change
T& pop();					// Note change

private:
T* stack;					// Note change
int topOfStack;
int size;

void grow();
void copyStack(const Stack&);
};

#endif
```

Using the Template Stack
```
#include <iostream.h>
#include "Stack.cp"

void main()
{
Stack<int> me;

Stack<float> you;

Stack<char> them;

for (int k = 0; k < 10; k++)
me.push(k);

you.push(11.234);

them.push('w');

cout 	<< me << endl
<< you << endl
<< them << endl;
}

```
Output
```Stack(9,8,7,6,5,4,3,2,1,0)

Stack(11.234)

Stack(w)

```

Implementation of Stack (1 of 4)
```

template <class T> Stack<T>::Stack(int StartSize)
{
size = StartSize;
stack = new T[StartSize];
topOfStack = 0;
}

template <class T> Stack<T>::Stack(const Stack<T>&
oldStack)
{
topOfStack = 0;
size = 0;
copyStack(oldStack);
}

template <class T>
Stack<T>& Stack<T>::operator=(const Stack<T>&
oldStack)
{
if (this != &oldStack) {

delete stack;

copyStack(oldStack);
}

return *this;
}

template <class T> Stack<T>::~Stack()
{
delete stack;
}

```

Implementation of Stack (2 of 4)
```
template <class T>
int Stack<T>::isEmpty() const
{
if (topOfStack == 0) return 1;
else return 0;
}

template <class T>
int Stack<T>::isFull() const
{	return 0;
}

template <class T>
void Stack<T>::push(const T& item)
{
if (topOfStack == size) grow();
stack[topOfStack++] = item;
}

template <class T>
T& Stack<T>::pop()
{
return stack[--topOfStack];
}

```

Implementation of Stack (3 of 4)
```
template <class T>
void Stack<T>::grow()
{
T *oldStack = stack;

int oldSize = size;

size += size/2 + 1;

stack = new T[ size ];

assert(stack  != 0 );

// copy elements of old array into new

for ( int ix = 0; ix < oldSize; ++ix )
stack[ ix ] = oldStack[ ix ];

delete oldStack;
}

template <class T>
void Stack<T>::copyStack(const Stack<T>& oldStack)
{
size = oldStack.size;

stack = new T[size];

for (int K = 0; K < oldStack.topOfStack;K++)
push(oldStack.stack[K]);
}

```

Implementation of Stack (4 of 4)
```

template <class T>
ostream& operator<<(ostream& output, Stack<T>&
aStack) {

output  << "Stack(" ;

output  << aStack.stack[aStack.topOfStack - 1];

for (int K = aStack.topOfStack - 2; K>= 0; K--)
output  << "," << aStack.stack[K];

output << ")";

return output;
}
```

Be careful with Templates
This does not compile?WHY?
```
#include <iostream.h>
#include "Stack.cp"

class foo
{
public:
int name;
};

void main()
{
Stack<foo> bar;
}
```

Stack class assumes types implement "<<"
```

#include <iostream.h>
#include "Stack.cp"

class foo
{

friend ostream&  operator<<(ostream&, foo&);

public:
int name;
};

ostream&  operator<<(ostream&  output, foo& bar )
{
output  << "foo(" ;
output  << bar.name;
output << ")";
return output;
}

void main()
{
Stack<foo> bar;
}
```

Why So Complicated?
Smalltalk Stack Equivalent
```
name: #Stack
superclass: Environment@#Object
classInstanceVars: nil
namedInstanceVars: #(stack)
classPoolVars: nil

initialize
stack := List new.

new
^(super new) initialize

asString
^'Stack(', (stack reverse)  asString , ')'

isEmpty
^stack isEmpty

isFull
^False

pop
^stack removeAt: (stack size)

push: item