· Templates – Allow you to define functions and classes that have parameters for type names.
o Function Templates
§ Syntax – The function declarations and definitions should begin with a template prefix which tells the compiler that the declaration or function that follows is a template and that ‘T’ is the type parameter.
//Example
template<class T>
int someFunction(T var1);
§ The compiler behaves as if it produces all definitions for the types used for T. When the compiler gets the function call, it notices the types of arguments, and then uses the template to produce a function definition of the type parameter T replaced with the argument type.
§ Some Functions may require more than one parameter type. To do this, you add the types in the template prefix, function declaration and function definition.
//Example
template<class T1, class T2>
int someFunction(T1 var1, T1 var2, T2 var3);
§ Note: Some compilers do not allow separate compilation of templates, so you may need to include the template definition with the code that uses it (i.e., directly or using a #include).
§ Note: the word “class” in the template prefix is a throwback to the early days of templates. ANSI/ISO changes this word to “typename” (which is a better name that matches what the intention is). However, “class” is used almost exclusively in the real world. Recommendation – use the word “class” instead of “typename”.
o class Templates
§ Syntax – Precede the class definition with a template prefix which tells the compiler that the class is a template class of type T.
//Example
template<class T>
class SomeClass
{
public:
SomeClass();
SomeClass(T var1, T var2);
etc...
};
§ Function definitions of the class should each have a template prefix as well.
//Example
template<class T>
int someFunction(T var1);
o Detailed Example – The following example uses templates to create multiple linked lists from multiple data files and allow for changes to be made (and saved) to each type of linked list. The use of templates simplifies the code by allowing us to use types as parameters, thus minimizing the need for duplicate code to keep track of multiple linked lists.
// Example
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
// Person Class and Implmentation
class Person
{
public:
Person(string fName, string lName, int age)
: _fName(fName), _lName(lName), _age(age) {}
~Person() {}
void setFirstName(string fName) { _fName = fName; }
string getFirstName() const { return _fName; }
void setLastName(string lName) { _lName = lName; }
string getLastName() const { return _lName; }
void setAge(int age) { _age = age; }
int getAge() const { return _age; }
bool matchTarget(string lName) const;
void display() const;
private:
string _fName;
string _lName;
int _age;
};
bool Person::matchTarget(string lName) const
{
return (_lName == lName);
}
void Person::display() const
{
cout << "\n*****************************************************\n";
cout << "Name: " << getFirstName() << " " << getLastName() << endl;
cout << "Age: " << getAge() << endl;
cout << "\n*****************************************************\n";
}
// Pet Class and Implmentation
class Pet
{
public:
Pet(string petName, string petType, string petBreed, int age)
: _petName(petName), _petType(petType),
_petBreed(petBreed), _age(age) {}
~Pet() {}
void setPetName(string petName) { _petName = petName; }
string getPetName() const { return _petName; }
void setPetType(string petType) { _petType = petType; }
string getPetType() const { return _petType; }
void setPetBreed(string petBreed) { _petBreed = petBreed; }
string getPetBreed() const { return _petBreed; }
void setAge(int age) { _age = age; }
int getAge() const { return _age; }
bool matchTarget(string lName) const;
void display() const;
private:
string _petName;
string _petType;
string _petBreed;
int _age;
};
bool Pet::matchTarget(string petName) const
{
return (_petName == petName);
}
void Pet::display() const
{
cout << "\n*****************************************************\n";
cout << "Name: " << getPetName() << endl;
cout << "Type: " << getPetType() << endl;
cout << "Breed: " << getPetBreed() << endl;
cout << "Age: " << getAge() << endl;
cout << "\n*****************************************************\n";
}
// Node Class definition and In-line Implementations.
template<class T>
class Node
{
public:
Node() { _data = NULL; _link = NULL; }
Node(T* data, Node<T>* link) : _data(data), _link(link) {}
~Node() { if(_data) delete _data; }
void setData(const T* data) { _data = data; }
T* getData() const { return _data; }
void setLink(Node <T>* ptr) { _link = ptr;}
Node<T>* getLink() const { return _link; }
private:
T *_data;
Node<T>* _link;
};
// Function for inserting node at head of list
template<class T>
void headInsert(T* data, Node<T>*& head)
{
head = new Node<T>(data, head);
}
// Function for deleting node at head of list
template<class T>
void headDelete(Node<T>*& head)
{
Node<T>* pDiscard = head;
head = head->getLink();
delete pDiscard;
}
// Function for inserting in the middle or end of the list
template<class T>
void insertNode(const T* data, Node<T>* pPutAfterMe)
{
pPutAfterMe->setLink(new Node<T>(data, pPutAfterMe->getLink()));
}
// Function for deleting in the middle or end of the list
template<class T>
void discardNode(Node<T>* pDiscardMe, Node<T>*& head)
{
if(pDiscardMe == head)
{
headDelete(head);
return;
}
Node<T>* pBeforeNode = head;
while( (pBeforeNode->getLink() != pDiscardMe) &&
(pBeforeNode->getLink() != NULL))
pBeforeNode = pBeforeNode->getLink();
if(pBeforeNode->getLink() == NULL)
{
cout << "\nCannot find node to discard.\n";
return;
}
pBeforeNode->setLink(pDiscardMe->getLink());
delete pDiscardMe;
}
// Function to search through the linked list
template<class T, class T2>
Node<T>* search(Node<T>* found, const T2 target)
{
if(found == NULL) // Empty list case
{
cout << "\n*****************************************************\n";
cout << "The list is currently empty.";
cout << "\n*****************************************************\n";
return NULL;
}
while(!(found->getData()->matchTarget(target)) &&
(found->getLink() != NULL))
found = found->getLink();
if(found->getData()->matchTarget(target))
return found;
else
{
cout << "\n*****************************************************\n";
cout << "Item Not found.";
cout << "\n*****************************************************\n";
return NULL;
}
}
// Function to display one person of the linked list
template<class T>
void displayNode(Node<T>* current)
{
if(current == NULL) // Empty list case
{
cout << "\n*****************************************************\n";
cout << "The list is currently empty.";
cout << "\n*****************************************************\n";
return;
}
current->getData()->display();
}
// Function to display the current contents of the linked list
template<class T>
void displayList(Node<T>* current)
{
if(current == NULL) // Empty list case
{
cout << "\n*****************************************************\n";
cout << "The list is currently empty.";
cout << "\n*****************************************************\n";
return;
}
do
{
current->getData()->display();
current = current->getLink();
} while (current != NULL);
}
template<class T>
void deleteList(Node<T>*& head)
{
if(head == NULL)
return;
Node<T>* current = NULL;
while(head != NULL)
{
current = head->getLink();
delete head;
head = current;
}
}
template<class T1, class T2>
int getLinkedLists(Node<T1>*& personList, Node<T2>*& petList)
{
ifstream inFile1, inFile2;
int age;
// Person Variables
Person *pPerson;
string lastName, firstName;
// Pet Variables
Pet *pPet;
string petName, petType, petBreed;
// Open the People data file to read in the People linked list
inFile1.open("people.txt");
if(inFile1.fail())
{
cout << "\nWarning: Could not open the People data file for reading.\n";
}
// Read into the linked list from the People data file
while((inFile1 >> firstName) && (inFile1 >> lastName) &&
(inFile1 >> age))
{
pPerson = new Person(firstName, lastName, age);
headInsert(pPerson, personList);
}
inFile1.close();
// Open the Pet data file to read in the Pet linked list
inFile2.open("pet.txt");
if(inFile2.fail())
{
cout << "\nWarning: Could not open the Pet data file for reading.\n";
}
// Read into the linked list from the Pet data file
while((inFile2 >> petName) && (inFile2 >> petType) &&
(inFile2 >> petBreed) && (inFile2 >> age))
{
pPet = new Pet(petName, petType, petBreed, age);
headInsert(pPet, petList);
}
inFile2.close();
return 0;
}
template<class T1, class T2>
void saveLinkedLists(Node<T1>* personList, Node<T2>* petList)
{
ofstream outFile1, outFile2;
// Open the People data file to write out the linked list
outFile1.open("people.txt");
if(outFile1.fail())
{
cout << "\nCould not open the People data file for writing.\n";
return;
}
if(personList == NULL)
{
cout << "\nWriting an empty list.\n";
outFile1.close(); // Makes an empty list
return;
}
// Write the linked list to the data file
while(personList != NULL)
{
outFile1 << personList->getData()->getFirstName() << " ";
outFile1 << personList->getData()->getLastName() << endl;
outFile1 << personList->getData()->getAge() << endl;
personList = personList->getLink();
}
outFile1.close();
// Open the Pet data file to write out the linked list
outFile2.open("pet.txt");
if(outFile2.fail())
{
cout << "\nCould not open the Pet data file for writing.\n";
return;
}
if(petList == NULL)
{
cout << "\nWriting an empty list.\n";
outFile2.close(); // Makes an empty list
return;
}
// Write the linked list to the data file
while(petList != NULL)
{
outFile2 << petList->getData()->getPetName() << endl;
outFile2 << petList->getData()->getPetType() << endl;
outFile2 << petList->getData()->getPetBreed() << endl;
outFile2 << petList->getData()->getAge() << endl;
petList = petList->getLink();
}
outFile2.close();
return;
}
int main()
{
// Person variables
Node<Person> * pPersonStart = NULL;
Node<Person> * pPersonCurrent = NULL;
Person* pPerson = NULL;
string lastName, firstName;
// Pet variables
Node<Pet> * pPetStart = NULL;
Node<Pet> * pPetCurrent = NULL;
Pet* pPet = NULL;
string petName, petType, petBreed;
// General variables
int age;
int choice, choice2;
if(getLinkedLists(pPersonStart, pPetStart))
return 1;
do
{
do
{
cout << "\n\nThe ABC People and Pet Registry\n\n";
cout << "1= Person, 2= Pet, 5= Quit\n\n";
cout << "Choice> ";
cin >> choice;
} while ((choice < 1) || (choice > 5) || (choice == 3) || (choice == 4));
if(choice == 5)
{
saveLinkedLists(pPersonStart, pPetStart);
deleteList(pPersonStart);
deleteList(pPetStart);
return 1;
}
do
{
cout << "1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit\n\n";
cout << "Choice> ";
cin >> choice2;
} while ((choice2 < 1) || (choice2 > 5));
switch(choice)
{
case 1:
switch(choice2)
{
case 1:
cout << "Last Name: ";
cin >> lastName;
cout << "First Name: ";
cin >> firstName;
cout << "Age: ";
cin >> age;
pPerson = new Person(firstName, lastName, age);
headInsert(pPerson, pPersonStart);
break;
case 2:
cout << "Last Name: ";
cin >> lastName;
pPersonCurrent = search(pPersonStart, lastName);
if(pPersonCurrent)
discardNode(pPersonCurrent, pPersonStart);
break;
case 3:
cout << "Last Name: ";
cin >> lastName;
pPersonCurrent = search(pPersonStart, lastName);
if(pPersonCurrent)
displayNode(pPersonCurrent);
break;
case 4:
displayList(pPersonStart);
break;
case 5:
saveLinkedLists(pPersonStart, pPetStart);
deleteList(pPersonStart);
deleteList(pPetStart);
return 0;
break;
}
break;
case 2:
switch(choice2)
{
case 1:
cout << "Pet Name: ";
cin >> petName;
cout << "Pet Type: ";
cin >> petType;
cout << "Pet Breed: ";
cin >> petBreed;
cout << "Age: ";
cin >> age;
pPet = new Pet(petName, petType, petBreed, age);
headInsert(pPet, pPetStart);
break;
case 2:
cout << "Pet Name: ";
cin >> petName;
pPetCurrent = search(pPetStart, petName);
if(pPetCurrent)
discardNode(pPetCurrent, pPetStart);
break;
case 3:
cout << "Pet Name: ";
cin >> petName;
pPetCurrent = search(pPetStart, petName);
if(pPetCurrent)
displayNode(pPetCurrent);
break;
case 4:
displayList(pPetStart);
break;
case 5:
saveLinkedLists(pPersonStart, pPetStart);
deleteList(pPersonStart);
deleteList(pPetStart);
return 0;
break;
}
break;
}
} while (1);
saveLinkedLists(pPersonStart, pPetStart);
deleteList(pPersonStart);
deleteList(pPetStart);
return 0;
}
// Sample Output #1
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: John Doe
Age: 50
*****************************************************
*****************************************************
Name: Paul Collins
Age: 37
*****************************************************
*****************************************************
Name: Grace Williams
Age: 26
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
The list is currently empty.
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 3
Last Name: Collins
*****************************************************
Name: Paul Collins
Age: 37
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 1
Pet Name: Spot
Pet Type: Dog
Pet Breed: Mixed
Age: 10
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 1
Pet Name: Mittens
Pet Type: Cat
Pet Breed: Mixed
Age: 6
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: Mittens
Type: Cat
Breed: Mixed
Age: 6
*****************************************************
*****************************************************
Name: Spot
Type: Dog
Breed: Mixed
Age: 10
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 3
Pet Name: Spot
*****************************************************
Name: Spot
Type: Dog
Breed: Mixed
Age: 10
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 2
Pet Name: Mittens
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: Spot
Type: Dog
Breed: Mixed
Age: 10
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 3
Last Name: Collins
*****************************************************
Name: Paul Collins
Age: 37
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 2
Last Name: Collins
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: John Doe
Age: 50
*****************************************************
*****************************************************
Name: Grace Williams
Age: 26
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: Spot
Type: Dog
Breed: Mixed
Age: 10
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 5
Press any key to continue
// Sample Output #2. I restarted the program and listed the pets and people.
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 1
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: Grace Williams
Age: 26
*****************************************************
*****************************************************
Name: John Doe
Age: 50
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 2
1= Add, 2= Delete, 3= Find, 4= Display List, 5= Quit
Choice> 4
*****************************************************
Name: Spot
Type: Dog
Breed: Mixed
Age: 10
*****************************************************
The ABC People and Pet Registry
1= Person, 2= Pet, 5= Quit
Choice> 5
Press any key to continue
· Standard Template Library – Not covered in this class, but read Chapter 19 for pertinent information on the STL.