Templates and Intro To The Standard Template Library (Vectors)
Templates and Intro To The Standard Template Library (Vectors)
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
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)
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
5
Function Templates vs. Overloaded Functions
l With overloaded functions: Each overloaded function we write still must be
written individually:
l For example:
n and
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.
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 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;
int main()
{
int intValue;
double doubleValue;
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 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
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)
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;
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 *
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;
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
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
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;
//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;
24
In Class Exercise
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
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
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
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 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.
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()
}
}
34
Example #6 – Class Templates
/*Destructor for the SimpleVector class*/
template <typename T>
SimpleVector<T>::~SimpleVector()
{
if(arraySize > 0)
delete[]aptr;
}
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];
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
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
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 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
41
Notes on Templates and Friends
l I only put the ones we need for the in class exercise
(next) here
42
In Class Exercise
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
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 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)
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
51
Near Containers
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
57
Creating Container Objects
l To create a list of int, write
l list<int> mylist;
n Requires the list header file
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 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
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
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 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)
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 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());
69
Example #10 – STL Algorithms
l This program demonstrates the STL
count algorithm
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%
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