Lab 8 (On templates)

Programming Workshop 2 (CSCI 1061U)

Winter 2021

Faculty of Science

Ontario Tech University


Introduction

The goal of this lab is to learn about templates in C++. Consider the following example for a template definition for a swap function that uses templates to simplify swapping two values for different types.

template<typename T>
void my_swap(T& a, T& b) {
    T tmp = a;
    a = b, b = tmp;
}

This uses a template with the type parameter argument T, which is used within the context of our function to facilitate swapping different types, we can now make use of the my_swap function for a multitude of types with ease as shown in the following code snippet.

#include <iostream>
#include <string>

using namespace std;

int main() {
    int a = 1, b = 2;
    double c = 3.0, d = 4.0;
    string alice = "alice", bob = "bob";

    my_swap(a, b);
    cout << "a = " << a << ", b = " << b << endl;

    my_swap(c, d);
    cout << "c = " << c << ", d = " << d << endl;

    my_swap(alice, bob);
    cout << "alice = " << alice << ", bob = " << bob << endl;

    return 0;
}

Part A - Descriptive Statistics

As we have seen the power of templates for use in simplifying code by reducing redundancy by templatizing our code. In part A we are going to make use of the C++ vector library and templates to create our own custom class Stats, we wish to create a class Stats with the following attributes:

  1. A Stats class with a private member _data that is a vector that uses the template definition for the type.

  2. A constructor which takes an array of values of type T called data and an int size argument. It adds the data to the internal vector, must make use of templates for the type.

  3. An add function which takes an argument value of type T and adds that to the internal _data vector.

  4. A average function which computes the average of _data, this can return a type double.

  5. A min function which returns the minimum value in _data, you will need to make use of templates for the return type.

  6. A max function which returns the maximum value in _data, you will need to make use of templates for the return type.

Your solution should assess your Stats class by performing the following in main():

  1. Create three instances of Stats, one for each of the following types: short, int, double.

  2. Add values of each type to the Stats instance.

  3. Display the average, min, max function results for each Stats instance.

You may use the following code snippet as a starting point for your main() function and to test your solution.

int main() {
    Stats<short> s1 = Stats<short>((const short[]){1, 2, 3, 4, 5}, 5);
    s1.add(6);

    cout << "shorts average: " << s1.average() << endl;
    cout << "shorts min: " << s1.min() << endl;
    cout << "shorts max: " << s1.max() << endl;

    return 0;
}

Part B - Creating a Linked List

In the first half we made extensive use of vectors to create our Stats class, in this second half we’re going to create our own implementation of a Singly Linked List, which we can use to support storing a collection of different data types.

A Linked List makes it possible for our solution to use dynamic memory allocation to create a container that can store data of different types through the application of templates.

Create a struct, used to store the elements of the linked list called Node:

  1. A struct called Node, which uses templates for the member data.

  2. A member called next, which also uses templates for a pointer to type Node.

Create your own custom LinkedList class. Your implementation will be a singly linked list which makes use of templates to support storing different types of data, ensure that your solution has the following:

  1. A class called LinkedList, which has private member pointers _head and _tail to Node for the linked list head and tail.

  2. A constructor, which should null initialize the head and tail class members.

  3. add function, which takes an argument value that is added to the linked list.

  4. remove function, which takes an argument value and if it is found in the linked list removes it from the linked list. Be careful, this is more difficult than it appears, your linked list must update the linkage correctly after removals.

  5. head function, which returns the head of the linked list.

  6. tail function, which returns the tail of the linked list.

  7. show function, which iterates through each value in the linked list and displays each value using cout.

You may use the following code snippet for main() to evaluate your solution.

int main() {
    LinkedList<int> li;
    for (int i = 10; i > 0; --i) {
        li.add(i);
    }
    li.show();

    li.remove(10);
    li.remove(5);
    li.remove(1);
    li.show();

    return 0;
}

Submission

Submit part-a.cpp and part-b.cpp via Canvas.