0% found this document useful (0 votes)
43 views73 pages

Templates and Intro To The Standard Template Library (Vectors)

The document discusses function templates in C++. It explains that function templates allow writing generic functions that can work with different data types. The compiler generates specialized functions from the templates based on the data types used. It provides an example of a function template for calculating the square of a number.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views73 pages

Templates and Intro To The Standard Template Library (Vectors)

The document discusses function templates in C++. It explains that function templates allow writing generic functions that can work with different data types. The compiler generates specialized functions from the templates based on the data types used. It provides an example of a function template for calculating the square of a number.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 73

Advanced C++

1. Templates (Chapter 6 pages 246-248 and


Chapter 18)
2. Introduction to the STL (vectors) – this is
MY material – Ch 15 in the new book is more )
Kristina Shroyer

1
Organization of this Material
l In the old book Templates were covered ENTIRELY in Chapter 14
n I thought this was good because I personally think it is good to understand
templates before learning the STL (standard template library)
n However the NEW book disagrees

l In the NEW BOOK


n Function templates are chapter 6 pages 246-248
n Class Templates are Chapter 18
♦ My material is easier than Chapter 18 so read the slides first

l For the STL


n What I currently have in here is a basic intro (more basic than the new book
Chapters of 15-16) and I focus on vectors – my material is different than the
book for now but the concept of course is the same

l NOTE: All of this material is on EXAM 3 – it is NOT on Exam 2


Chapter Objectives
In this lecture you’ll learn (these items are on exam 3 – the final):
l To use function templates to conveniently create a group of related
(overloaded) functions.

l To distinguish between function templates and function-template specializations.

l To use class templates to create a group of related types.

l To distinguish between class templates and class-template specializations.

l To overload function templates.

l To understand the relationships among templates, inheritance and static


members

l Introduction the standard template library and the vector class


n We may do more on the standard template library later in the class time permitting

3
Introduction
l Function templates and class templates allow the
programmer to specify with a single segment of code:
n an entire range of related (overloaded) functions (function
templates)
n or an entire range of related classes (class templates)

l Function and class templates allow for generic


programming
n You'll see we don't have to specify data types and function
templates will work correctly based on the data types of the
arguments passed into them
n You can write a single function for sorting an array and it will work
on int type arrays, double type arrays, string type arrays
and many more, by generating the proper function template
specialization when the function is called.

l In Java templates are called generic functions/classes


n Generics came about in Java 6.0 and onwards

4
Function Templates vs. Overloaded Functions
l Concept: A function template is a generic function that can work
with different data types.
n The programmer writes the generic specifications of the function in a way
that will allow it to work with different data types.
n When the compiler encounters a call to the function it generates code to
handle the specific data types used in the function call
n So basically we're going to have one generic function that can be used with
different types of data

l Overloaded functions (which you should have learned in your


beginning programming class):
n remember you are overloading functions when you have two or more
functions that have similar functionality with the same name but different
function signatures (number, order and types of parameters)
n make programming convenient because only one function name must be
remembered for a set of functions that perform similar operations
♦ However, each of the overloaded functions still must be written
individually – templates will in certain cases eliminate the need for this

5
Function Templates vs. Overloaded Functions
l With overloaded functions: Each overloaded function we write still must be
written individually:

l For example:

int square(int number)


{
return number * number;
}

n and

double square(double number)


{
return number * number;
}

n these overloaded functions have the exact same functionality, the only differences between
these two functions are the data types of their parameters and the data types of their return
values.

l In these types of situations (where the overloaded functions have the exact
same functionality except for their data types) it will be more convenient to
write a function template than an overloaded function
n So these function templates will allow us to write a single function definition that works with
many different data types, instead of having to write a separate function for each data type
possible to be used

6
Function Templates
l Function Templates: are used to produce overloaded functions that
perform identical operations on different types of data
n Programmer writes a single function-template definition
n Compiler generates separate object-code functions (function-template
specializations) based on argument types in calls to the function template
n Similar to macros in C, but with full type checking
♦ Function templates, like macros, enable software reuse. Unlike macros, function
templates help eliminate many types of errors through the scrutiny of full C++ type
checking.

l Think of a function template not as an actual function but more as a "mold"


that the compiler uses to generate one or more functions called function
template specializations
n When writing a function template you will not specify the data types of the parameters,
of return value, or of the local variables
n Instead you will use a type parameter to specify a generic data type
n When the compiler encounters a call to the function it examines the data types of
its arguments and generates the function code that will work with those
arguments

l It's important you understand the difference between function


templates and function template specializations – function template is
the generic mold, and the compiler creates function template specifications
from that generic mold

7
Function Template Definitions
l Here is a function template for the square function:
template <typename T>
T square(T number)
{
return number * number;
}
l Function-template definitions
n are preceded by a template header (also called a template prefix) (template<typename T> in
our example)
♦ The header starts with the keyword template
♦ It is followed by a list of template parameters
l each template parameter is enclosed in angle brackets (< and >)
l Each template parameter (generic data type) is preceded by keyword class or keyword typename (both
are interchangeable) followed by a parameter name that stands for the generic data type(s) (type
parameter(s))
l So in the example there is one generic data type T
§ This is used to specify types of arguments to, local variables in and return type of the function template
n Keywords class and typename are used to specify function template parameters and mean
"any fundamental (primitive) or user defined type"
n I believe class and typename can be used interchangeably but typename seems newer to
me so I TRIED to change class to typename in my examples but I didn't get all of them
♦ Examples
template< typename T >
template< class ElementType >
template< typename BorderType, typename Filltype >

l Note: All generic data types defined in the function template header must appear at
least once in the function parameter list or in the return type
8
Function Template Definitions
l Here is a function template for the square function:
template <typename T>
T square(T number)
{
return number * number;
}

l Function-template definitions (continued)


n once you finished with the template header (template <class T> in this case), then the function
definition is written as usual except type parameters are substituted for actual data type names

l In our example this is the function header:


n T square(T number)
♦ T is a generic data type (also called a type parameter)
♦ The header defines square as a function that returns a value of type T and uses a parameter number which
is also of type T

l When the function square is used in a program:


n The compiler examines each call to square and fills in the appropriate data type for T (in order to
generate a function template specialization – this is when the memory is created from the mold)
♦ The following call uses an int argument:
int y, x = 4;
y = square(x);

l this causes the compiler to GENERATE the following function template specialization:
int square(int number)
{
return number * number;
}
9
Define Templates in Source Files
l Most C++ compilers require the complete definition of a
template to appear in the client source-code file that uses the
template.
n This seems to be true in the new standard as well unless I'm
missing something
n For this reason and for reusability, templates are often defined in header
files, which are then #include into the appropriate client source-code
files.
n For class templates, this means that the member function
implementations are also defined in the header file.

l This is also why I've rarely if ever seen template prototypes for
template functions in procedural programs, instead they tend to
appear defined in their entirety at the top of the file
n In Example 1 (next slide) I showed how to do the program with and
without a prototype for a procedural program, I do NOT think this will
work or is recommended for an object oriented program (separating the
prototype from the definition)

10
Function Template Example #1
//Simple procedural function template program

#include <iostream>
#include <iomanip>
using namespace std;

//template definition for the square function


template <typename T> //template header..T is the generic data type
T square(T number)
{
return number * number;
}

int main()
{
int intValue;
double doubleValue;

cout << setprecision(5);


cout << "Enter an iteger: " ;
cin >> intValue;
cout << "The square of " << intValue << " is " << square(intValue) << endl;

cout << "\nEnter a floating piont value: ";


cin >> doubleValue;
cout << "The square of " << doubleValue << " is " << square(doubleValue) << endl;

return 0;
}

11
Function Template: Example #1
l Example #1 continued
n Since the compiler encountered two calls to square in the program each
with different parameter types:
♦ The compiler generated two instances of the function
l One with an int parameter and an int return type
l One with a double parameter and a double return type

l This means a function template:


n is only used for the DEFINITION of the generic function and by itself
does NOT cause memory to be used
n An actual instance of the function is ONLY created in memory when the
compiler encounters a call to the template function

l Note in the example that the template appears before all calls to
square
n As with regular functions, the compiler must already know the template's
contents when it encounters a call to the template function
n Templates should be placed near the top of the program or in a header file

12
Function Template: Example #2
l Example #2: The swap function template
n In a lot of applications there is a need for swapping the contents of two variables of the same type

l A good example is an array sorting function


n If the array was an array of ints there would be a need for a function like this:
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}

n If the array was an array of string objects the function would need to look like this
void swap(string &a, string &b)
{
string temp = a;
a = b;
b = temp;
}

l Since the only difference in the coding of these two functions is the type of variables swapped a
template function can be used (QUESTION: Why did I pass by reference??):
template <class T>
void swap(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}

13
Function Template: Example #2
l The swap template function is actually
available in the libraries that come with
standard C++ compilers (it is part of the
STL – more on that later)

l The function is declared in the algorithm


header file
n Example 2 illustrates this

14
Function Template: Example #2
#include <iostream>
#include <string>
#include <algorithm> //needed for swap
using namespace std;

int main()
{
char firstChar, secondChar;
int firstInt, secondInt;
string firstString, secondString;

//get and swap two characters


cout << "Enter two characters: ";
cin >> firstChar >> secondChar;
cout << "BEFORE the swap: firstChar = " << firstChar << " secondChar = " << secondChar << endl;
swap(firstChar, secondChar);
cout << "AFTER the swap: firstChar = " << firstChar << " secondChar = " << secondChar << endl;

//get and swap two integers


cout << "\nEnter two integers: ";
cin >> firstInt >> secondInt;
cout << "BEFORE the swap: firstInt = " << firstInt << " secondInt = " << secondInt << endl;
swap(firstInt, secondInt);
cout << "AFTER the swap: firstInt = " << firstInt << " secondInt = " << secondInt << endl;

cout << "\nEnter the first string: ";


cin.ignore();
getline(cin, firstString);
cout << "Enter the second string: ";
getline(cin, secondString);
cout << "BEFORE the swap: firstString = " << firstString << " secondString = " << secondString <<
endl;
swap(firstString, secondString);
cout << "AFTER the swap: firstString = " << firstString << " secondString = " << secondString <<
endl;

return 0;
}
Using Operators in Function Templates
l The square function in Example #1 applies the
operator * to its function template
n This function will work fine as long as the type of parameter
passed to it supports the * operator
n So it will work on types like: long, int, and double
n It will also work with any user defined class type that overloads
the operator *
n Errors will result if square is used with types that do not support
the operator *

l Always remember that templates will only work with


types that support the operations used by that template
n For example a class can only be used with a template that uses
the <, >, <=, <=, !=, and == operators if the class overloads
those operators

16
Function Templates: Example #3
l Example #3: Since the string class overloads all the relational operators it can be used with template
functions that compute the minimum of an array of items

#include <string>
#include <iostream>
using namespace std;

//template for the minimum of an array


template <typename T> //header, defines generic data type T
T minimum(T arr[], int size)
{
T smallest = arr[0]; //set first element to be smallest
for(int k = 0; k < size; k++)
{
if(arr[k] < smallest) //if needed update smallest (ie the new smallest
{
smallest = arr[k];
}
}

return smallest;
}

int main()
{
int arr1[] = {40,20,35};
string arr2[] = {"Zoe", "Snoopy", "Bob", "Waldorf"};

cout << "The minimum number in arr1 is: " << minimum(arr1,3) << endl;
cout << "The minimum string in arr2 is: " << minimum(arr2,4) << endl;

return 0;
}

17
Function Templates with Multiple Types

l More than one generic type can be used in


a function template
n Meaning you can make a function template for a
function that may take and return different generic
types of parameters (rather than just one generic
T like we've been using)

l The next Example (Example #4):


n illustrates this by taking as parameters a list of
three values of any printable type, printing the list
in order and then printing the list in reverse

18
Function Template Example #4 (multiple params)
#include <string>
#include <iostream>
using namespace std;

//template function
template <typename T1, typename T2, typename T3> //has three generic types - each one must be
//used at least once
void echoAndReverse(T1 a1, T2 a2, T3 a3)
{
cout << "Original Order is: " << a1 << ", " << a2 << ", " << a3 << endl;
cout << "Reversed Order is: " << a3 << ", " << a2 << ", " << a1 << endl;
}

int main()
{
echoAndReverse("Computer", 'A', 18);
cout << endl;
echoAndReverse(2.5, "All", 4);

return 0;
}

19
Performance Tip
l Although templates offer software-reusability
benefits, remember that multiple function-
template specializations and class-template
specializations are instantiated in a program (at
compile time), despite the fact that the template
is written only once.
n These copies can consume considerable memory.
n This is not normally an issue, though,
♦ because the code generated by the template is the same size
as the code the programmer would have written to produce
the separate overloaded functions.

20
Overloading with Function Templates
l Function Templates may be overloaded
n Remember overloaded functions have the same name but different
function signatures

l A function template may be overloaded two ways:


1. with other function templates that specify the same name but different
parameters
2. Nontemplate functions that specify the same name but different
parameters/parameter lists (so different signatures)

l The compiler chooses the best function or specialization to match


the function call
n A nontemplate function is chosen over a template specialization in
case of a tie
♦ A tie meaning there are two matches and one is a template function and the
other is a non-template function
n Otherwise, multiple matches result in a compilation error (ambiguous
function call )
n As normal no matches also result in a compilation error

21
Overloading with Function Templates
l To determine which function to call when a function call is invoked
the compiler performs the following matching process
n First, the compiler finds all function templates that match the function
named in the function call and creates specializations based on the
arguments in the function call
n Next, the compiler finds all ordinary functions (non-template functions)
that match the named function call
n If ONE of the ordinary functions or function template specializations is
best for the function call, that one is used
n If ONE ordinary function and ONE template function specialization are
equally good matches for the function call, the ordinary function is used
n Otherwise, if there are MULTIPLE (other than the cases above)
matches for the function call, the complier will consider the function call
ambiguous and generate an error message

22
Function Template: Example #5 (overloading)
#include <iostream>
using namespace std;

template <typename T>


T sum(T val1, T val2)
{
return val1 + val2;
}

template <typename T>


T sum(T val1, T val2, T val3)
{
cout << "Template function is executing" << endl;
return val1 + val2 + val3;
}

//nontemplate function...notice the compler chooses this one over the template "tie"
/*double sum(double v1, double v2, double v3)
{
cout << "NON template function is executing" << endl;
return v1 + v2 + v3;
}*/

int main()
{
double num1, num2, num3;

cout << "Enter the first number: ";


cin >> num1;
cout << "\nEnter the second number: ";
cin >> num2;
cout << "The sum of the two numbers is: " << sum(num1, num2) << endl;

cout << "\nEnter the first number: ";


cin >> num1;
cout << "\nEnter the second number: ";
cin >> num2;
cout << "\nEnter the third number: ";
cin >> num3;
cout << "The sum of the three numbers is: " << sum(num1, num2, num3) << endl;
return 0;
}
Defining Function Templates
l When you define function templates
n It is often helpful to start by writing a non-template
version of the function and converting it to a
template after the non-template version as been
tested
n The conversion is easy, you just:
♦ prefix the function definition with an appropriate
template header like: template <typename T>
♦ and the systematically replace the relevant data
type in the function with the generic type T

24
In Class Exercise

l For your discussion board you are going to


do this exercise if you are an online class
l Otherwise we will do this together in class.
C++11 – Trailing Return Types
l The book does not explain what this is very well but it sounds like a
trailing return type is a way of creating an inferred return type
n I'm not sure if they mean the template function doesn't have to specify?
♦ This is something that might be interesting to look into

l All I can seem to find is the HOW on making a trailing return type not
the why…
n To make a trailing return type place the keyword auto before the template
and end with ->T (with T being the generic type)
♦ template <typename T>
♦ auto maximum(T x, T y, T z) ->

l My guess is this is beyond the scope of our material but I thought I'd
put this in here – someone may be interested in researching it for a
final project or something
Class Templates
l Concept: templates may be used to create generic classes and
abstract data types
l Function templates are used whenever we need several different
functions with the same problem solving logic, but that differ in the
types of parameters they work with.
l Class templates can be used in the situation where we need
several classes which only differ in the types of their data
members and/or in the types of the parameters of their member
functions

l Declaring class templates:


n is done in a similar way of defining function templates
n Class templates (or parameterized types)
♦ Class-template definitions (.h file) are preceded by a header
l Such as template< typename T >
♦ Type parameter T can be used as a data type in member functions and data
members (member variables)
♦ Multiple type parameters can be specified using a comma-separated list
l As in template< typename T1, typename T2 >

27
Example #6 – Class Templates
l For this example we're going to define a class
for a NumberArray, so this will be a generic
class type that will work and perform operations
on any type of numeric array (int, double, float
etc.)
n The generic class is going to be called SimpleVector

l Just like with other things in our slides pretend


vector doesn't exist and we are creating our own
simple vector data type that works for all
numeric arrays

28
Example #6 – Class Templates
l Here is our template for the class SimpleVector:
template <typename T>
class SimpleVector
{
private:
T *aptr; //a pointer to an array of a generic type T
int arraySize;

public:
SimpleVector() //inline default constructor
{
aptr = nullptr;
arraySize = 0;
}
SimpleVector(int); //constructor with one argument
SimpleVector(const SimpleVector&); //copy constructor
~SimpleVector(); //destructor

int size() //inline function


{
return arraySize;
}

T& operator[](int); //overloaded [] operator


void print();
};
l This class template will store elements of type T in a dynamically generated array.
n This is why the pointer member aptr, which will point to the base of this array is
of type T, because the array should be able to be any numeric type
l Note however that the size member is not of type T but of type int, this makes
sense because the size of an array is always an int regardless of its type
29
Example #6 – Class Templates
l Notice this at the beginning of our class header
file:
template <class T>
class SimpleVector

n The T acts as a placeholder to allow any data type of SimpleVector


class to be created
♦ You don't specifically use the identifier T when creating an instance of the
class - any valid identifier can be used when you create an instance of
SimpleVector (we'll see in a second)
♦ This T which is the type of SimpleVector is mentioned generically
throughout the class as T in both the member function definitions and the
class header

l Member functions of a class template ARE REQUIRED TO BE


function templates

30
Example #6 – Class Templates
l You can think of the SimpleVector template as a generic pattern that can be specialized
to create a class of type SimpleVector to hold double, long, string or any other type
you can define
n Remember SimpleVector is just an attempt at creating a basic array class that will work
with different types of data generically

l CREATING INSTANCES OF CLASS TEMPLATES


l The rule is you create an instance of a class template by appending a list of the actual
type(s) in angled brackets to the name of the class template followed by the instance
name:
n SimpleVector<double> dArr; is the name of a class that stores arrays of type double
n SimpleVector<string> sArr; is the name of a class that stores arrays of type string
n SimpleVector<char> cArr; is the name of a class that stores arrays of type char

l Class templates are called parameterized types because they require one or
more type parameters (when instances are created) to specify how to customize
a "generic class" to form a class template specialization
n The compiler generates the specialization info in memory when instances are created

31
Example #6 – Class Templates
l Defining a template member function (remember all member functions are REQUIRED to
be templates) of a template class inside the class definition (.h) (in other words an inline
function) is straightforward (it KNOWS the type of the class is generic T):
n An example is the default constructor in our SimpleVector class definition:
SimpleVector() //inline default constructor
{
aptr = 0;
arraySize = 0;
}

l NOTE: The declarations and definitions of the class template member functions
should all be in the same header file or with most compilers you will get an error.

l Remember from earlier:


n Most C++ compilers require the complete definition of a template to appear in the client source-
code file that uses the template.
♦ For this reason and for reusability, template definitions are often defined in header files, which are then
#included into the appropriate client source-code files.
♦ For class templates, this means that the member functions are also defined in the header file – not
necessarily in the class definition (so they are NOT all inline) but in the .h file (most are outside the
closing curly of the .h so they are NOT inline) – we're going to follow this idea when creating our class
templates.

32
Example #6 – Class Templates
l NOTE: The declarations and definitions of the class template member functions should all be in
the same header file or with most compilers you will get an error.

l To define a template member function outside of the class (but still in the HEADER FILE as per last
slides) you must:
n prefix the function definition with a template header that specifies the list of type parameters
n and then within definition you must use the name of the class template followed by a list of type parameters in angled
brackets whenever you use the NAME of the class
n And of course every time the generic type comes up use the type (T in this case) as normal
n NOTE: even though we are not using separate files for implementation and declaration for the templates you should define
non-inline functions outside the class
♦ The rule still stands that only inline (very short one or two line) functions should be defined inside the class definition
n For example:
template <typename T>
SimpleVector<T>::SimpleVector(int s)
{
arraySize = s;
aptr = new T[s];
for(int count = 0; count < arraySize; count++)
{
aptr[count] = T(); //calls the constructor for object T,default value
//so if T is a string for instance T() calls the default
//constructor for a string, if T is primitive the compiler will use 0 in
//place of T()
}
}

l So we have a template header and before the scope resolution operator we have the name of the class
followed by the type parameters of the class in angled brackets

33
Example #6 – Class Templates
l Let's look at the various function definitions – NOTE they are all in the .h file but OUTSIDE the class
definition

/*Constructor for SimpleVector class. Sets the size of the array and allocates
memory for it*/
template <typename T>
SimpleVector<T>::SimpleVector(int s)
{
arraySize = s;
aptr = new T[s];
for(int count = 0; count < arraySize; count++)
{
aptr[count] = T(); //T() is the default constructor for the generic data type, if T is
//primitive the compiler will use 0 in place of T()
}
}

/*Copy Constructor for the SimpleVector class*/


/*NOTE: There is an exception to the rule of attaching the list of type parameters to the name of
the template class. The list and angled brackets that enclose it can be omitted whenever the
name if the class is being used within the scope of the template class. The copy constructor
is an example because T is not appended to the parameter (argument type) SimpleVector*/
template <typename T>
SimpleVector<T>::SimpleVector(const SimpleVector& obj)
{
arraySize = obj.size();
aptr = new T[arraySize];
for(int count = 0; count < arraySize; count++)
{
aptr[count] = obj[count];
}
}

34
Example #6 – Class Templates
/*Destructor for the SimpleVector class*/
template <typename T>
SimpleVector<T>::~SimpleVector()
{
if(arraySize > 0)
delete[]aptr;
}

//overloaded [] operator. The argument is a subscript. This function returns


//a reference to the element in the array indexed by the subscript. Since
//we haven't done exception handling yet if they enter an invalid subscript
//I'm just having it return the first element and an error message
template <typename T>
T& SimpleVector<T>::operator[](int sub)
{
if(sub < 0 || sub > arraySize)
{
cout << "Invalid Subscript!" << endl;
return aptr[0];
}
else
return aptr[sub];
}

/*prints all the entries in the array*/


template <typename T>
void SimpleVector<T>::print()
{
for(int count = 0; count < arraySize; count++)
{
cout << aptr[count] << ", ";
}
cout << endl;
}

35
Non-type template Parameters and Default
Types for Class Templates
l Class SimpleVector used only a type parameter in the template header
l It is also possible to use non-type template parameters
n These non-type template parameters can have default values and are treated as
const values (so they can't change in the class)
l You can also use default parameters on regular generic types
l Example #6a - non-type parameters:
♦ Modified Template header for a SimpleArray template class (NOTE: this is different
than SIMPLE VECTOR, no dynamic memory allocation):
template< typename T, int elements >
Declaration:
SimpleArray< double, 100 > salesFigures;
♦ This declaration would instantiate (at compile time) a 100 element SimpleArray class
template specialization of double values named salesFigures.
♦ The class header for this modified SimpleArray class might contain a private data
member with a declaration such as:
l T arr[elements];

l When appropriate, specify the size of a container class (such as an array


class or a stack class) at compile time (possibly through a non-type
template parameter).
n This eliminates the execution-time overhead of using new to create the space
dynamically.

36
Non-type template Parameters and Default
Types for Class Templates
l Example#6b - default parameters:
n Example
♦ Modified Template header:
template< typename T = int >
Declaration (creates a class specification that is an array of
ints):
SimpleVector<> scores;

37
Class Templates and Inheritance
l Inheritance can be applied to class
templates
n We're going to go through a simple example

l We're going to go through an Example that


illustrates templates and inheritance
n This example is merely to show you the
mechanics of Inheritance used with class
templates

38
Example #7 – Class Templates & Inheritance
l Example #7: This example is going to show a class
SearchableVector derived from our SimpleVector
class
n Design wise I wouldn't use inheritance for this but instead I would
just add the find function to the original SimpleVector class
n HOWEVER, this is a good illustration of Inheritance and
templates TECHNICALLY only – not design wise

l The first thing we have to do is indicate to the compiler


that we are defining a new class template based on
another, already existing class template:
template <typename T>
class SearchableVector: public SimpleVector<T>
{
//members of the class go here
};

39
Example #7 – Class Templates & Inheritance
l Example #7 continued: This example is going to show a class SearchableVector derived
from our SimipleVector class

l The class has three constructors


n The first constructor is designed to dynamically allocate an array of size elements of type T, which it does by invoking
the base class constructor and passing it the parameter size.
n This constructor creates an array of the specialized class with all the elements initialized to default values of type T.

n SearchableVector(int size): SimpleVector<T>(size){}

l The second constructor takes a parameter that is a base class object, a copy of which is to be
searched.
n The constructor just passes its parameter to the base class copy constructor.
n This works because a SearchableVector is a SimpleVector
n SearchableVector(SimpleVector<T> &obj): SimpleVector<T>(obj){}

l The last constructor is the copy constructor for the SearchableVector class.
n Because the initialization of a SearchableVector is the same as the initialization of a SimpleVector, the
SearchableVector copy constructor simply passes its argument to the copy constructor of its base class
(SimpleVector)

l All other functions are inherited (note I added a getSize() function to SimpleVector – I think I did
that for the other examples also)

l The only template member function added is the find function, let's look at Example #7

40
Notes on Templates and static Members

l static data members of a class template


n Each class-template specialization (remember a
specialization is the object code for a specific type of the
function – so there may be an int specification, a
double specification, a string specification etc etc)
has its own copy of each static data member
♦ All objects of that ONE specialization (so all int
specializations for example) share that one static data
member
n Each class-template specialization gets its own copy of
the class template’s static member functions

41
Notes on Templates and Friends
l I only put the ones we need for the in class exercise
(next) here

l Templates and friends


n Assume class template X with type parameter T as in:
template< typename T >
class X{};

n A function can be the friend of EVERY class-template


specialization instantiated from a class template
friend void f1();
§ f1 is a friend of X< double > , X< string > , etc.

n A function can be the friend of ONLY a class-template


specialization with the same type argument
friend void f2( X< T > & );
§ f2( X< float > & ) is a friend of X< float > but NOT a friend
of X< string >

42
In Class Exercise

l If you are a hybrid class - we are now


going to do an in class exercise on class
templates
l If you are an online class we will do this for
our Zoom Conference
Introduction to the STL
l These slides are slides I made based on another
book because at the time our book did not have
a good chapter on it

l The new book does have a good chapter – it's


Chapter 15
n I haven't incorporated all of Chapter 15 here due to time
limitations but I did start incorporating some of it
n If you are interested in this topic for your final project feel
free to use anything from Chapter 15 in your proposal
The Standard Template Library - Intro
l Concept: The Standard Template Library contains many templates
for useful algorithms, data types, and data structures
n If you haven't taken CSIS 130 or CSIS 211 think of a data structure as a way
of storing and organizing data – an array is a data structure

l In addition to the run time library which you have used throughout
the book, C++ also provides a library of templates
n This library of templates is called the Standard Template Library (STL) and
contains numerous templates for implementing abstract data types and
algorithms

l Note: Pre-standard C++ compilers may not support the STL

l The most important structures in the STL are containers and


iterators
n containers: classes that store data and impose some organization on it (a
data structure)
n iterators: like pointers; mechanisms for accessing elements in a container

45
STL Intro: Containers
l Containers are templatized data structures
n They are data structures capable of sorting objects of
almost ANY data type (with some restrictions)

l There are three styles of container classes


n First-class containers
♦ sequence and associative containers (both ordered and
unordered)
n container adapters
♦ sequences containers that are only allowed to be viewed in a
constrained manner
n near containers
♦ these exhibit some but not all capabilities of first class
containers
STL Intro: Iterators
l Iterators
n Have properties similar to pointers
n are used to manipulate container elements
n Manipulating containers with iterators is convenient and
provides a lot of power when combined with the STL
algorithms

l Built-in arrays can also be manipulated using the


Standard Library algorithms using iterators as
pointers
n I haven't tried this – remember the algorithms library of the
STL has function templates designed to work on containers
STL Intro: Algorthms

l Algorithms are function templates that


perform data manipulations (usually on
containers) such as:
n searching, sorting, and comparing elements or
ENTIRE containers
Tips
l Avoid reinventing the wheel
n program with containers (and other standard library
components) of the C++ standard library

l Error Prevention Tip


n The prepackaged templatized Standard Library containers
are sufficient from most applications
♦ using them reduces testing and debugging time

l Performance Tip
n The STL was conceived and designed for performance and
flexibility
The Standard Template Library - Intro
l There are four categories of container classes in STL:
n sequence containers (this is the one we are going to look at – these are
LINEAR containers): organize data sequentially, similar to an array – there
is a natural way to organize things based on their position in the container
(structure) and that order of items (position in the container) can be used to
access data. These include array (this is the new C++11 fixed array we've
mentioned), vector, deque, forward_list (new in C++11) and list
n ordered associative containers: use keys to allow data elements to be
quickly accessed – data is organized by key rather than by position in the
container – keys are maintained in a sorted order (These include set,
multiset, map, and multimap)

n unordered associative containers: I believe this is the same as an


ordered associative container except keys are not maintained in sorted order
(These include unordered_set, unorderd_multiset,
unordered_map, and unordered_multimap)

n container Adaptors (enable a program to view a sequence container in


an constrained matter): stack (LIFO), queue (FIFO), priority_queue
(highest priority element is the first one out)

50
More on Sequential Containers
l sequential containers: organize data sequentially based on the
data's position in the container, as in an array. These include:
array, forward_list, vector, deque, and list

l Because a sequential container organizes the items it stores as a


sequence, it can be said to have a front and a back

l A container is said to provide random access to its contents if it is


possible to specify a item within the container and jump directly to
that item without having to go through all the items in the container
before it to reach the item
n Remember arrays are random access, vectors are also containers with
random access
n Positions used in random access containers are usually specified by giving
an integer specifying the position of the desired item in the container
♦ The integer may specify a position relative to the beginning of the container,
the end of the container, or relative to some other position

51
Near Containers

l Exhibit some but not all properties of first


class containers
n built-in arrays
n bit-sets
n valarrays
Common Container Functions
l Most containers provide similar functionality
n I have a handout (printout) of functions that are available in
most STL containers
♦ Note overloaded operators are NOT provided for
priority_queues and are NOT provided for the unordered
associative containers
♦ Note member functions rbegin, rend, crbegin and crend are
not available in forward_list

l Before using a container study its capabilities


n I'm focusing mainly on vector in this lecture but you can
easily find info on the other containers
First Class Container – Common Nested Types

l Nested types are class types defined


INSIDE each class definition
n These are used in template-based declaration of
variables, parameters to functions and return
types from functions
n Mainly in this class we are worried about iterator
♦ The idea is each container has it's own iterator data
type to properly iterate through said container

l I have another couple printouts for this


Requirements for Container Elements
l Before using a STL container you need to make sure that the
type of objects being stored in the container has a minimum set
of functionality
n When an object is stored in a container a copy of the object is made
♦ this means objects for containers MUST provide copy constructors and
assignment operators
l Whether the object uses memberwise assignment (default copy constr, assign
operator) or a custom copy contructor and assignment operator depends on if
the object has dynamic memory allocation
n The ordered associative containers and many of the algorithms (for all
containers) require objects be compared
♦ this means the object should provide comparison operators (<, >, ==
etc)
Sequential Containers
l sequential containers: organize and access data sequentially

l Let's look specifically at a few of these containers (I'm really only looking at array and vector here – you'll need to research the others if
you are interested)

l array:
n A sequence of items implemented as a fixed size array
n All items must be the same data type
n Similar to the general concepts you used with built-in arrays but this is a template so you create as such
n must #include <array>

l vector:
n A sequence of items (same data type) implemented as an array that can automatically grow as needed during program execution.
♦ Items can efficiently be added and removed from the vector at its end
♦ Insertions and removals from the middle or beginning of the vector are not as efficient
n must #include <vector>

l deque:
n A sequence of items that has a front and back.
n Items can efficiently be added and removed from the front and back
n Insertions and removals from the middle are not as efficient
n (template version of a queue)

l forward_list:
n A sequence of items that allows quick additions and removals from any position
n (the template version of a singly linked list)

l list:
n A sequence of items that allows quick additions and removals from any position
n (the template version of a doubly linked list)

l We’re going to look specifically at vector in this section since some people here have not taken the data structures class yet

56
Ordered Associative Containers
l ordered associative containers: use keys to allow data elements to be quickly
accessed. These include set, multiset, map, and multimap

l Sequential containers use the position of an item within the sequence to access their
data

l In contrast, associative containers associate a key with each item stored , and then
use the key to retrieve the stored item
n A telephone book is an associative container: the items (values) stored are the telephone numbers
and the key is the name, so each telephone number is associated with a name

l Four ordered associative containers:


n map: Maps a set of keys to data elements. Each key is associated with a unique data element and
duplicate keys are not permitted
♦ A map is a container that requires each value stored to be associated with a key
♦ each key may be associated with only one value
♦ Once a key is used, no other value with the same key maybe added to the map
n multimap: Like a map except a key may be associated with multiple values
n set: Stores a set of keys, no duplicate values are allowed
♦ A set is like a map in which the value stored is the same as the key
♦ Thus the set can be viewed as storing keys only
♦ No item may be stored twice in a set, duplicates are not permitted
n multiset: like a set except duplicates are permitted

57
Creating Container Objects
l To create a list of int, write
l list<int> mylist;
n Requires the list header file

l To create a vector of string objects, write


vector<string> myvector;
n Requires the vector header file

These are just class template specializations like we just learned

58
Iterators
l Iterators are objects that behave a lot like pointers (using one is like using a
pointer)
n They are used to access items stored in first class containers
n Iterators hold a state of information sensitive to the particular containers in
which they operate so iterators are nested types inside EACH type of
container
♦ An iterator is an object (instance) of a class declared inside the container class
n The iterator overloads pointer operators such as the increment operator (++)
and the decrement operator (--) in order to provide pointer like behavior

l Each container object in the STL (vector, list etc) provides member
functions like begin() and end() that return the beginning and ending
iterators for the object
n The iterator object returned from a container's begin() member function points
to the item at the beginning of the container (if the container is non-empty)
n The iterator object returned from a container's end() member function points to
the item at the end of the container (if the container is non-empty)
♦ Note that with a vector end() points to the memory space or “item” what would occur
just after the end of the vector
n begin() and end() only work with sequential containers

59
Iterators
l There are five different types of iterators available for use with the various STL
containers

l Random Access: Can move forward and backward, and can jump to a specific data
element in a container
n Combines the abilities of the bidirectional iterator with the ability to directly access any element of
the container
n These are the only iterators I talk about in our lecture because they work for vectors (which is what
I'm mainly discussing) and they also work for the new array template (the fixed size array) which
you may be interested in looking up for your final project

l Bidirectional: Can move forward or backward in the container (uses the ++ and the
-- operators)
n So adds backward direction to the forward iterator

l Forward: Can only move forward in the container (uses the ++ operator)
n Combines the capabilities of the input and output iterators and retains their position in the container

l Input: Used to read an element from a container. Can be used with cin to read
information from an input device or a file

l Output: Used to write an element to a container. Can be used with cout to write
information to an output device or a file

60
Iterator Operations

l I cut and pasted them from your book to the next


slide

l Note:
n In addition the operators shown iterators must provide
default constructors, copy constructors and overloaded
assignment operators
n A forward iterator does everything an input or output
iterator does
n A bidirectional iterator does everything a forward iterator
does
n A random access iterator does everything a bidirectional
iteretor does (so it does ALL the operations shown)
Iterator Operations

Remember random
access can do
anything the other
types can do since
they build on each
other
Iterator Operations (random access)
Using Iterators
l Remember each STL container has begin() and
end() functions that return iterators to access items
stored in a container

l An iterator is an object of an inner class called


iterator that is defined inside a container class
n due to the fact that an iterator is an inner class of a container,
the use of the scope resolution operator (::) is necessary to
obtain an iterator for a given container

l For example to define an iterator object named iter


that will work with a class of type vector<int> we
write:
n vector<int>::iterator iter;

64
Using Iterators
l To define an iterator for a vector of int and have it initialized to the
beginning of the container vect we write:
n vector<int> vect; //create a vector object vect of type
//int
n vector<int>::iterator iter = vect.begin();
//iter points to the first item in vect

l Once an iterator is defined and made to point to the beginning of


the container, the items in the container at the position of the
iterator can be accessed by dereferencing the pointer

l An iterator can be made to move to the next item in the array by


incrementing it (++), if the iterator is bidirectional it can be made
to move to the previous element by decrementing it (--)

l The statements below print the value of an element in a container


and then moves the iterator to the next element:
n cout << *iter;
n iter++;

65
The Vector Container
l The book doesn't have a comprehensive vector container list but I
found a decent one online
n http://www.cplusplus.com/reference/vector/vector/
n Let's take a look at it

l Look at the description for the member function begin()

l Look at the description for the member function end()


n Note end returns an iterator pointing to just AFTER the last element
of the vector
♦ This means you should not dereference an iterator of a vector whose
value is end()

l Look at pop_back()

l Look at push_back(value)

66
Example #8 – Iterator and Vector
l Example #8: Note the inclusion of the vector header file which is required
for the vector container
n The vector is one of the simplest types of containers in the STL

l If you’re interested for your final project you can look into iterators
and vectors in more detail or into one of the other containers and its
vectors in more detail
n (this material is just a basic intro to this topic – this is covered in a lot more detail in CSIS 211)
n We just don’t have enough time to look at these more closely since I also want to cover
exception handling and files

l Side Note:
n We can’t cover everything in detail unfortunately
n The idea is to give you enough knowledge in class that you can apply that to learn new things
n You are in an advanced class and should be able to apply your knowledge to similar and new
concepts, ideas and applications
♦ If you know for example one compiler and aren’t able to adapt and apply that knowledge to
another container that is a real problem for you in real life
♦ Businesses do not care that you “prefer” one compiler or think your way is “better” than theirs –
they want you to apply your skills in a personable way to help the business the team reach a
goal (and usually make a profit)

67
Algorithms and the STL
l The algorithms provided by the STL are in the header
algorithms (we already saw the swap earlier) are
implemented as function templates and perform
various operations on elements of containers and
sometimes non container elements (such as swap)

l There are many algorithms in the STL


n If you have the book Chapter 16 goes into detail

l I have a link to the algorithms library for you


n http://www.cplusplus.com/reference/algorithm/

l Let's look at a few of them

68
Example #9 – STL algorithms
l The program illustrates the random_shuffle, sort and binary_search
algorithm templates
n Let's look at it and run it

l The random_shuffle function randomly rearranges the elements of a


container, in the program it is called like this:
n random_shuffle(vect.begin(), vect.end());
n The function takes two arguments, which together represent a range of elements within
a container
♦ The first argument is an iterator to the first element in the range
♦ The second argument is an iterator to just after the last element in the range
♦ Meaning the range includes the first argument and excludes the last
♦ These arguments tell random_shuffle to rearrange randomly all the elements from the
beginning to the end of the vect container

l The sort algorithm also takes arguments that are a range of items
(elements), all the elements in the range are sorted in ascending order
n sort(vect.begin(), vect.end());

l the binary_search algorithm searches a range of elements for a value, if the


value is found the funtion returns true, otherwise the function returns false
n binary_search(vect.begin(), vect.end(), 7);

69
Example #10 – STL Algorithms
l This program demonstrates the STL
count algorithm

l Let's take a look

70
In Class Program (if time)
l Rewrite Example #10 so it does the following:
n first have it print out the values from 1-100 and the number of
times and percentage of times each value appears in the vector
♦ The printout should look similar to this:
number #times in vector % times
---------- ---------------------- -----------
1 5 5%
2 7 7%

♦ etc etc etc! (don't stop at 2!)

n Next ask the user for a value they would like to remove from the
vector, remove all occurrences of that value from the vector and
re-print the above chart with the value removed

71
Array template

l Here's a link if you are interested


n http://www.cplusplus.com/reference/array/array/?k
w=array
This is just an overview

l If you have CSIS 211 you might be interested in


looking at some of the other containers either in
Ch 15 of the book or on that website I linked to
for vectors and arrays
n It could be interesting for the final project if you don't have
one yet

l Also for anyone else if you have the book there


is more information in Ch 15-16 and on the
website
n These containers are very useful when programming

You might also like