Advanced Templates

Templates with Multiple Type Parameters

A class template may have more than one type parameter. The template below defines a class that encapsulates pairs of objects -- the first is the key, the second is the data. #include <iostream> #include <string> using namespace std; // defines Pair as a template with two // template parameters template < class Key, class Data > class Pair { public: // default constructor Pair( ); // destructor ~Pair( ); // copy constructor Pair( const Pair<Key, Data>& pair); // equality operator bool operator== (const Pair<Key, Data>& rhs) const; private: Key m_key; Data m_data; }; // Pair's equality operator template <class K, class D> bool Pair<K, D>::operator== (const Pair<K,D>& rhs) const { return m_key == rhs.m_key && m_data == rhs.m_data; } int main ( ) { string bob = "bob"; string mary = "mary"; // use pair to associate a string and its length Pair< int, string > boy (bob.length(), bob); Pair< int, string > girl (mary.length(), mary); // make a new pair using copy constructor Pair<int, string> dad = boy; // check for equality if (bob == girl) cout << "They match\n"; // use Pair for names and Employee object Employee john, mark; Pair< string, Employee> boss ("john", john); Pair< string, Employee> worker( "mark", mark); if (boss == worker) cout << "A real small company\n"; return 0; }

Templates can have Nontype Parameters

Not all of the parameters for a template need be class type parameters. For instance, we could have written the SmartArray template to include the size as a nontype template parameter as shown below. This technique avoids the necessity of using dynamically allocated memory for the SmartArray class. template <class T, int size> class SmartArray { public: SmartArray ( ); // other members private: int m_size; T m_data[ size ]; }; template< class T, int size> SmartArray<T, size>::SmartArray( ) { m_size = size; }

Templates as Parameters

When we wish to pass a template class to a function, that function becomes a function template. Here's the definition for a function that sorts the elements of a smart arrary. We want to use it for all types of smart arrays, so we pass the smart array template as the parameter. template <class T> void Sort ( SmartArray<T>& theArray) { // code here }

Templates and Friends

We can make functions friends of templates too. For example, if we want to output SmartArrays using operator<<, we define the function as a template as above template <class T> ostream& operator<< (ostream& out, const SmartArray<T>& theArray) { // code here } In the SmartArray class definition we declare operator<< to be our friend in the usual way, but we must tell the compiler that operator<< is a template function. One easy way to do this by including "<>" after the name of the function. template <class T> class SmartArray { friend ostream& operator<< <> (ostream& out, const SmartArray<T>& theArray); // the rest of the SmartArray class definition }; There is one other key component to completing your implementation of a templated friend in your application, in order to allow the compiler to understand where the operator belongs and which class it belongs to. We use a technique called "forward declaring" in order to notify the compiler of each of these components. Essentially "forward declaring" is prototyping everything that you will be declaring: template <class T> class FooClass; // forward-declaring class template <class T> ostream& operator<< (ostream& out, const FooClass &foo); // forward-declaring insertion stream template <class T> class FooClass { public: friend ostream& operator<< <> (ostream& out, const FooClass &foo); private: }; template <class T> ostream& operator<< (ostream& out, const FooClass &foo) { // implementation }


Last Modified: Monday, 28-Aug-2006 10:16:05 EDT