1 Linked Lists III Template Chapter 3
2 Objectives You will be able to: Write a generic list class as a C++ template. Use the template in a test program.
3 Issues in the int List Class The list can only hold integers. Solution: Make it a template.
4 Templates Templates are a feature in C++ that permit code to be more reusable. They have blanks, called parameters, that can be automatically filled in with type names at compile time. Rather than having to define separate classes for lists of ints, doubles, Circles, Dogs, Cats, etc., we can define a single List template. A user of the template can supply the name of the class that will be the data in list nodes. The compiler handles the substitution of the class name specified by the user for the parameter into the template definition. Result is a List class specialized for the users class.
5 Limitations of Template A class used as a template parameter must meet certain requirements. Must implement all operators used by the template methods. Typically = (Assignment operator) Copy constructor
6 Templates We have two kinds of templates in C++. Function templates. Class templates. In each, parameters can be specified for one or more types. The parameters are used as if they were real type names. The compiler substitutes real type names, specified by the user, for the parameters when the template is used.
7 C++ Templates The word template is a C++ keyword In front of a function definition, it specifies that what follows is … a pattern for a function definition not a real function definition. Type parameters appear within angle brackets ( ) before the function definition. Normal function parameters appear within parentheses, as in normal function definitions.
8 Caution A function template cannot be split across files. Specification and implementation must be in the same file. Just a.h file. No.cpp file.
9 A Function Template template T is a parameter void Swap (T &first, T &second) { T temp = first; first = second; second = temp; } The keyword typename can be used instead of the keyword class in the first line.
10 Function Template Instantiation When the compiler encounters a call to a function defined as a template, it generates a real function definition substituting the type(s) of the function arguments for the template parameter(s). The function call looks exactly like a call to a normally defined function. Example: swap (a[i], a[i+1]);
11 Class Templates We can define templates for classes as well as for functions. Specify one or more template parameters in front of the class definition. The class definition uses the parameters as if they were real class names. Real class names must be provided as values for the parameters whenever the template is used.
12 General Form Of Class Template Declaration template <class TypeParam1, class TypeParam2,..., class TypeParamN> class SomeClass { //... members of SomeClass... }; Within the class definition, the class parameters TypeParam1, TypeParam2, … TypeparamN can be used as if they were real class names. The parameter names can be any valid C++ name. (Same rules as for variable names.) When the class is used, real class names will be provided and substituted for the parameters. class is a C++ keyword here.
13 Alternative Form Keyword typename can be used instead of keyword class in the template parameter list. template <typename TypeParam1, typename TypeParam2,..., typename TypeParamN> class SomeClass { //... members of SomeClass... };
14 Instantiating Class Templates Instantiate the template by writing a declaration of form SomeClass objectName; where Type represents a real class name and SomeClass is the name of the template class. Passes Type as an argument to the class definition template. Examples: Stack intStack; Stack stringStack; Compiler will generate two distinct definitions of Stack Two instances of the class definition One for ints and one for strings.
15 Rules For Class Templates 1. Member functions outside the class declaration must be function templates. 2. Member functions must be defined in the same file as the class declaration. 3. All uses of the template class name as a type must be parameterized.
16 Convert intDLList into a List Template Create a new project. List_Template_Demo Copy the files from intDLList2 into the project directory _01_24_Doubly_Linked_List_2/ _01_24_Doubly_Linked_List_2/ Add the.h file to the project. Rename as DLList.h
17 Convert intDLList into a List Template Modify the existing code for intDLList to make it a template. Have to copy the function definitions from the.cpp file into the.h file. Replace int by a class parameter. Replace class names by new parameterized class names.
18 The Node Class Definition //************************ DLList.h ***************** // Doubly-linked list template #ifndef DLLIST_H #define DLLIST_H template class DLLNode { public: T info; DLLNode *next; DLLNode *prev; DLLNode(T el, DLLNode *ptr1 = 0, DLLNode *ptr2 = 0) { info = el; next = ptr1; prev = ptr2; } };
19 Problem with the Listhead In the intDLList we create the Listhead with an info value of 0. The value is never used. We can't do this with a template. For an arbitrary class, T, 0 might not be a valid value. We need a constructor for class DLLNode that doesn't specify a value for info. Leaves info uninitialized in the Listhead.
20 Default Constructor for DLLNode Add to DLLNode class defintion: DLLNode() { next = 0; prev = 0; }
21 DLList Class Definition template class DLList { private: DLLNode * ListHead; public: DLList() { ListHead = new DLLNode (); ListHead->next = ListHead; ListHead->prev = ListHead; }
22 DLList Class Definition DLList(const DLList & original); DLList& operator=(const DLList & original); ~DLList(); int isEmpty() const { return ListHead->next == ListHead; } void addToHead(const T&); void addToTail(const T&); T deleteFromHead(); // Delete the head and return its info; T deleteFromTail(); // Delete the tail and return its info; void deleteNode(const T&); bool isInList(const T&) const; void printAll() const; };
23 Destructor template DLList ::~DLList(void) { while (!isEmpty()) { DLLNode *p = ListHead->next->next; delete ListHead->next; ListHead->next = p; }
24 addToHead template void DLList ::addToHead(const T& el) { DLLNode *p = new DLLNode (el); p->next = ListHead->next; p->prev = ListHead; ListHead->next->prev = p; ListHead->next = p; }
25 addToTail template void DLList ::addToTail(const T& el) { DLLNode *p = new DLLNode (el); p->next = ListHead; p->prev = ListHead->prev; ListHead->prev->next = p; ListHead->prev = p; }
26 deleteFromHead template T DLList ::deleteFromHead() { if (isEmpty()) { throw("Attempt to delete from empty list"); } T el = ListHead->next->info; DLLNode *tmp = ListHead->next; ListHead->next->next->prev = ListHead; ListHead->next = ListHead->next->next; delete tmp; return el; }
27 deleteFromTail template T DLList ::deleteFromTail() { if (isEmpty()) { throw("Attempt to delete from empty list"); } T el = ListHead->prev->info; DLLNode *tmp = ListHead->prev; ListHead->prev->prev->next = ListHead; ListHead->prev = ListHead->prev->prev; delete tmp; return el; }
28 deleteNode template void DLList ::deleteNode(const T& el) { DLLNode *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; } if (p == ListHead) { return; // It's not there. Claim success! } // p points to node to be deleted. p->prev->next = p->next; p->next->prev = p->prev; delete p; }
29 isInList template bool DLList ::isInList(const T& el) const { DLLNode *p = ListHead->next; while (p != ListHead && p->info != el) { p = p->next; } return p != ListHead; }
30 printAll template void DLList ::printAll() const { if (isEmpty()) { cout << "List is empty\n"; return; } DLLNode *p = ListHead->next; while (p != ListHead) { cout info << endl; p = p->next; } cout << endl; }
31 Copy Constructor // Copy constructor template DLList ::DLList(const DLList & original) { ListHead = new DLLNode (); ListHead->next = ListHead; ListHead->prev = ListHead; // Copy the original list DLLNode* p = original.ListHead->next; while (p != original.ListHead) { addToTail(p->info); p = p->next; }
32 Assignment Operator // Assignment operator template DLList & DLList ::operator=(const DLList & original) { if (this == &original) // Check for self assignment { return *this; } while (!isEmpty()) // Delete the current list contents { deleteFromTail(); } delete ListHead;
33 Assignment Operator ListHead = new DLLNode (); ListHead->next = ListHead; ListHead->prev = ListHead; // Copy the original list DLLNode * p = original.ListHead->next; while (p != original.ListHead) { addToTail(p->info); p = p->next; } return *this; }
34 Testing the Template Adapt the test driver for intDLList to use the DLList template. Parmeterize the template for int. Results should be identical to previous.
35 main.cpp #include #include "DLList.h" using namespace std; int main() { DLList myList;... myList = new DLList ();... myList = new DLList ();... Everything else is unchanged.
36 Program Running