Function Templates

Suppose we want to code up the max() function for different types:

template <class T> T max (const T& a, const T& b) { if ( a < b) return b; else return a; }

T is called the type parameter and can have any legal identifier name.

Using Function Templates

max( ) for int

When the compiler sees this code

int i1 = 1, i2 = 2, i3; i3 = max(i1, i2);

it creates this function:

int max (const int& a, const int& b) { if (a < b) return b; else return a; }

max( ) for float

When compiler sees this code:

float f1 = 1.2 f2 = 2.2, f3; f3 = max(f1, f2);

it creates this function:

float max (const float& a, const float& b) { if (a < b) return b; else return a; }

Note: the < operator overloaded.

max() for Strings??

When the compiler sees this code:

char *str1 = "abc"; char *str2 = "def"; cout << max(str1, str2) << endl;

it creates this function:

char* max (const char*& a, const char*& b) { if (a < b) return b; else return a; }

Is this really what you want? What really gets compared?

max() for Strings

Class Templates

Example: SmartArray

A SmartArray remembers the size of its array:

class SmartArray { public: SmartArray (int size = 100); // other members private: int m_size ; // always int int *m_theData ; // this int should change };

Nothing in the algorithms for the SmartArray code relies on the fact that this is an array of integers.

Class template for SmartArray

As with function templates, we use a template parameter ( T ) to take the place of the generic data type.

template <class T> class SmartArray { public: SmartArray ( int size = 100 ); // other members private: int m_size; T *m_theData; // array of any type };

Class Template Implementation

Each member function is a function template.

// SmartArray constructor template <class T> SmartArray<T>::SmartArray (int size) : m_size( size ) { // an array of Ts using T's default constructor m_theData = new T [m_size]; } ...

Using the SmartArray class template

Templates with Multiple Type Parameters

Templates with Non-type Parameters

Non-type parameters can be used to create a data structure with the specified initial size or specified initial value (e.g., vectors).

template <class T, int size> class SmartArray { public: SmartArray ( ); // other members private: int m_size; T m_data[ size ]; };

Templates as Parameters

When we wish to pass a (uninstantiated) template class to a function, that function becomes a function template.

template <class T> void Sort (SmartArray<T>& theArray) { // code here }

Note: not needed for instantiated template parameters

void foobar (vector<int>& A) { ... }

Template files

Templates and Friends

We can make functions friends of templates, but we must tell the compiler that operator<< is a template function by adding <>.

template <class T> class SmartArray { friend ostream& operator<< <> (ostream& out, const SmartArray<T>& theArray); // the rest of the SmartArray class definition } ;

Friends & Forward Declarations

We need to add forward class and function declarations to finish declaring a templated friend function.

// forward-declaring class template <class T> class SmartArray ; // forward-declaring insertion stream template <class T> ostream& operator<< (ostream& out, const SmartArray &foo);