Title: Templates
1Templates
- Generic Programming
- ECE 297
2Templates
- A way to write code once that works for many
different types of variables - float, int, char, string, List, Vector,
- Reference Problem Solving in C by Savitch,
Chapter 17
3Template Functions
4Types Functions
- All parameters and local variables in a function
must have a type - void swap_val (int a, int b)
-
- int temp
- temp a
- a b
- b temp
-
- void swap_val (double a, double b)
-
- double temp
- temp a
- a b
- b temp
-
OK. Function overloading
5Function Templates
- Allow you to write abstract algorithms
- Work for many types
- templateltclass VariableTypegt
- void swap_val (VariableType a, VariableType b)
-
- VariableType temp
- temp a
- a b
- b temp
-
template prefix defines a type parameter
Can use that type parameter instead of a
regular type In the function
6Using a Function Template
- templateltclass VariableTypegt
- void swap_val (VariableType a, VariableType b)
-
- VariableType temp
- temp a
- a b
- b temp
-
- int main ()
- int i1 5, i2 10
- swap_val (i1, i2)
- // Compiler will create swap_valltintgt
- float f1 1e6, f2 2e6
- swap_val (f1, f2)
- // Compiler will create swap_valltfloatgt
Template definition must come before template use
7Using a Function Template
swap_val.h
templateltclass VariableTypegt void swap_val
(VariableType a, VariableType b)
VariableType temp temp a a b b
temp
main.cpp
- include swap_val.h
- int main ()
- int i1 5, i2 10
- swap_val (i1, i2) // swap_valltintgt created
- float f1 1e6, f2 2e6
- swap_val (f1, f2) // swap_valltfloatgt
created
8Restrictions on Swap
templateltclass VariableTypegt void swap_val
(VariableType a, VariableType b)
VariableType temp temp a a b b
temp
?
- swap_val (int, int)
- swap_val (char, char)
- swap_val (List, List)
- swap_val (int, float)
- Works for any one type that has proper (deep
copy) operator
?
?
?
9Generic Minimum
- templateltclass VariableTypegt
- VariableType minimum (VariableType a,
VariableType b) -
- if (a lt b)
- return (a)
- else
- return (b)
-
- minimum (int, int)
- minimum (float, float)
- minimum (int20, int20)
- minimum (List, List)
- minimum (string, string)
- Works for any type that defines operatorlt
(reasonably)
?
?
?
?
?
10Generic Quicksort
- void QuickSort (int A, int left, int right)
- int PivotIndex SelectAndShuffle (A, left,
right) - if (PivotIndex gt left) //
Basis - QuickSort (A, left, PivotIndex-1) //
Recursion - if (PivotIndex lt right) //
Basis - QuickSort (A, PivotIndex1, right) //
Recursion -
- templateltclass Tbasegt
- void QuickSort (Tbase A, int left, int right)
- int PivotIndex SelectAndShuffle (A, left,
right) - if (PivotIndex gt left) //
Basis - QuickSort (A, left, PivotIndex-1) //
Recursion - if (PivotIndex lt right) //
Basis - QuickSort (A, PivotIndex1, right) //
Recursion -
11Generic Quicksort
- int SelectAndShuffle (int A, int left, int
right) - int i, PivotIndex
- PivotIndex left
- for (i left1 i lt right i)
- if (Ai lt Aleft)
- PivotIndex PivotIndex 1
- swap_val (Ai, APivotIndex)
-
-
- swap_val (Aleft, APivotIndex)
- return (PivotIndex)
-
12Generic Quicksort
- templateltclass Tbasegt
- int SelectAndShuffle (Tbase A, int left, int
right) - int i, PivotIndex
- PivotIndex left
- for (i left1 i lt right i)
- if (Ai lt Aleft)
- PivotIndex PivotIndex 1
- swap_val (Ai, APivotIndex)
-
-
- swap_val (Aleft, APivotIndex)
- return (PivotIndex)
-
13Template Classes
14Template Classes
- Can make templated (type-generic) classes
- Member functions
- Member data
- Most useful for container classes
- Classes that implement basic data structures
- List, Vector, Tree (Map),
15Example Pair of Data
- Often useful to store two pieces of data together
- key, value in ECE 244 lab5 (binary tree for DNS)
used together - string name, int ip (244 lab 5)
- Could want string name, string data
- or int key, float data
-
- Make a class that can store two arbitrary pieces
of data - first (any type)
- second (any type)
16Generic Pair Class
- templateltclass Tfirst, class Tsecondgt
- class MyPair
- public
- MyPair (Tfirst _first, Tsecond _second)
- void setFirst (Tfirst _first)
- void setSecond (Tsecond _second)
- Tfirst getFirst ()
- Tsecond getSecond ()
- private
- Tfirst first
- Tsecond second
-
In MyPair.h
17Generic Pair Class
- include MyPair.h
- int main ()
- MyPairltint,floatgt pair1(1, 2.5)
- cout ltlt pair1.getFirst() ltlt ltlt
pair1.getSecond() - ...
In main.cpp
Creates a variable named pair1 class (type) is
MyPairltint, floatgt
pair1
int first 1float second 2.5
18Generic Pair Class
- include MyPair.h
- int main ()
- MyPairltint,floatgt pair1(1, 2.5)
- cout ltlt pair1.getFirst() ltlt ltlt
pair1.getSecond() - MyPairltstring,doublegt tscore ("Your test
score", 7.5) - cout ltlt tscore.getFirst() ltlt " "
ltlt tscore.getSecond() ltlt endl - tscore.setFirst ("Revised test score")
- tscore.setSecond (9.5)
- cout ltlt tscore.getFirst() ltlt " " ltlt
tscore.getSecond() ltlt endl
In main.cpp
Creates a variable named tscore class (type) is
MyPairltstring, doublegt
tscore
string first Your test scoredouble second
7.5
19Generic Pair Class
- include MyPair.h
- int main ()
- MyPairltint,floatgt pair1(1, 2.5)
- cout ltlt pair1.getFirst() ltlt ltlt
pair1.getSecond() - MyPairltstring,doublegt tscore ("Your test
score", 7.5) - cout ltlt tscore.getFirst() ltlt " "
ltlt tscore.getSecond() ltlt endl - tscore.setFirst ("Revised test score")
- tscore.setSecond (9.5)
- cout ltlt tscore.getFirst() ltlt " " ltlt
tscore.getSecond() ltlt endl
In main.cpp
Program output
1 2.5 Your test score 7.5 Revised test score 9.5
20Generic Pair Class
Template prefix tells compiler this is a
templated function
In MyPair.h
- templateltclass Tfirst, class Tsecondgt
- MyPairltTfirst,TsecondgtMyPair (Tfirst _first,
- Tsecond _second)
- first _first
- second _second
-
- templateltclass Tfirst, class Tsecondgt
- void MyPairltTfirst,TsecondgtsetFirst (Tfirst
_first) - first _first
-
- // Rest of member function defintitions
Class name is MyPairltTfirst, Tsecondgt
21Function Definitions Where?
In MyPair.h
templateltclass Tfirst, class Tsecondgt MyPairltTfirs
t,TsecondgtMyPair (Tfirst _first,
Tsecond _second) first
_first second _second ... // Rest of
class member function definitions
include MyPair.h int main ()
MyPairltint,floatgt pair1(1, 2.5)
In main.cpp
- Usually bad style to define all member functions
in header file - But with templates, compiler must be able to
generate class as it sees the specific type to
build - ? Needs to see function definitions as it
compiles class instantiations - E.g. MyPairltint, floatgt in main.cpp
- Need to generate instructions (.o) for MyPair,
with a Tfirst int, and Tsecond float - Easiest to achieve by putting whole class
implementation in header file
22Writing Templates
- Write code for a specific type first
- Debug, test
- Convert to template
- Can get complex / subtle syntax errors
23STL Generic Algorithms
- Using the Standard Template Libraries
24STL
- Writing templates ? fairly hard
- Using templates easy productive
- Standard Template Library
- Fast, well-tested implementations of useful
algorithms and data structures
25STL References
Basic Reference Problem Solving in C by
Savitch, Chapter 18
Detailed reference cplusplus.com
Really nitty gritty details C Primer by
Lippman, Lajoie and Moo
26STL
- Writing templates ? fairly hard
- Using templates easy productive
- Standard Template Library
- Fast, well-tested implementations of useful
algorithms and data structures
27STL Generic Algorithms
Useful algorithms that work with many types in
ltalgorithmgt
templateltclass Tgt T max (T a, T b) if (a lt
b) return (b) else return (a)
ltalgorithmgt
include ltalgorithmgt using namespace std int
main ( ) double x 1.1, y 1.2 double
z max (x, y) int j 2, k 3 int i
max (j, k) z max (i, x) z max
(x, 2) z max (x, 2.0)
main.cpp
// OK ? max (int, int)
// Wont compile
// Wont compile
// OK! max (double, double)
28STL Generic Algorithms
- Also in ltalgorithmgt min (), sort ()
- Work for any one type that defines lt and
assignment (operator) - and lots more see cplusplus.com
- But I only use the very basic ones
29STL Container Classes
30STL Container Classes
- Most useful part of STL
- Data structures that just contain some other
data type / class - E.g. vector, linked list, binary tree of some
type - Can use to store any type of data (templated)
- Avoids a lot of repetitive coding of linked
lists, binary trees, etc.
31Vector
- Example motivation
- Want to read integers from cin to an array until
EOF - gt 1 -20 3 31 55 ltCtrlDgt
- Then pass the array on to the rest of the program
to process, print, examine, - Problem how big an array should we allocate?
- int array new int??
- Dont know until after the input is read!
- Could code up a linked list, load it, count
elements, then allocate array, copy data from
linked list, delete linked list
32Vector
- Wouldnt it be great to have something just like
an array that could grow as needed?
include ltvectorgt include ltiostreamgt using
namespace std vectorltintgt get_input ( )
vectorltintgt vec // vector of ints,
initially empty int val cin gtgt val
while ( !cin.fail() ) vec.push_back
(val) // Add new value to end of vector
cin gtgt val return (vec) //
Return the whole vector
main.cpp
33Vector Can Use Like Array
include ltvectorgt include ltiostreamgt using
namespace std . . . int main ()
vectorltintgt in_vals in_vals get_input ()
for (int i 0 i lt in_vals.size() i)
cout ltlt in_valsi ltlt cout ltlt endl
for (int i in_vals.size() 1 i gt 0 i--)
cout ltlt in_valsi ltlt
main.cpp
vectors know how many elements they contain.
Valid data from index 0 to size()-1
Fast, O(1), random access to any entry
How would I print out the vector in reverse order?
Input 1 -20 3 31 55 ltCtrlDgt Output 1 -20 3 31
55 55 31 3 -20 1
34Slightly Cleaner Version
int main () vectorltintgt in_vals in_vals
get_input () for (int i 0 i lt
in_vals.size() i) cout ltlt in_valsi ltlt
Compiler will give a type mismatch warning
(.size() is unsigned int). Harmless, but I prefer
to have no warnings.
Will make warning go away
for (int i 0 i lt (int) in_vals.size() i)
cout ltlt in_valsi ltlt
i now unsigned int ? watch out for gt 0 tests
C purists way
for (vectorltintgtsize_type i 0 i lt
in_vals.size() i) cout ltlt in_valsi ltlt
35How Does It Work?
vectorltintgt get_input ( ) vectorltintgt vec
// vector of ints, initially empty int
val cin gtgt val while ( !cin.fail() )
vec.push_back (val) // Add new value to end
of vector cin gtgt val return (vec)
// Return the whole vector
1
vec
1
-20
int array int size int capacity
1
2
3
4
5
0
2
1
-20
4
8
1
3
31
1
-20
3
31
55
Input
1
-20
3
31
55
36Vector Key Properties
- Efficient to add elements at end (push_back)
- Because when there isnt enough space it grows
the storage quite a bit (usually 2x) - Means even for a large number N of push_back(),
we get only a few array copies - O(1) on average
- Efficient random access to data
- Because internally the vector stores the data in
an array ? operator can be fast - O(1)
37Handy Constructors
include ltvectorgt using namespace std int main
() vectorltintgt vec1 // default
constructor size 0 vectorltintgt vec2(10) //
size 10, but values unknown vectorltintgt
vec3(10,-1) // size 10, all values -1
38Assignment Destruction
include ltvectorgt using namespace std int main
() int a new int10 int b new
int10 vectorltintgt v1(10), v2(10) a0
2 v10 2 . . . a b // OK?
v1 v2 // OK? delete a delete
b delete v1 // Should I?
No! Shallow copy
Yes! Proper deep copy defined in ltvectorgt
No! ltvectorgt defines a destructor cleans up its
internal array
39operator
include ltvectorgt using namespace std int main
() vectorltintgt v1 v1.push_back(-3)
v10 -2 // OK? v11 -2 // OK?
v1.push_back(-3) v11 -2 // OK?
Yes, entry 0 exists
No, cant create values with
Yes, can create values with push_back()
Yes, entry 1 exists now
- Really bad ? out of bounds array access and
memory corruption (maybe seg fault, maybe worse!) - Most compilers have an option to make vector
check the index value is between 0 and
size()-1 and print an error (g
-D_GLIBCXX_DEBUG) - Slows program down ? we have turned this on only
for the debug configuration of your milestone1
NetBeans project
40Shrinking a vector
include ltvectorgt using namespace std int main
() vectorltintgt v1 v1.push_back(1)
v1.push_back(2) for (int i 0 i lt
in_vals.size() i) cout ltlt in_valsi ltlt
v1.pop_back() // Removes one entry
from end of vector for (int i 0 i lt
in_vals.size() i) cout ltlt in_valsi ltlt
Output 1 2
Output 1
41Vectors should be familiar
- vectorltchargt
- almost same as ltstringgt
- Difference string defines some extra utility
functions - Otherwise a string really is a vectorltchargt
- Full reference on vector member functions at
http//www.cplusplus.com/reference/vector/vector/