Title: Template and Generic Programming
1SECTION 5
- Template and Generic Programming
2Templates
- Generic programming is about code that can be
used over a wide category of types. - The C template mechanism one or more types are
parameterized in the definition of a class or a
function. - Template provides a powerful mechanism for code
reuse. - Function template
- Class template
3Function Template
- To make a function general purpose, we can write
a function template with some unspecified generic
form of data element. - Function template function with
type parameter.
4Towards generic programming
- First example
- void copy(int from, int to, int size)
- for ( int i0 iltsize i )
- toi fromi
-
- int x10, y10
- double a5, b5
- copy( y, x, 10 ) // ok
- copy( b, a, 5 ) // compile time error
- We can overload function copy so it can work on
different data types. - Or, Can we write a generic copy?
5- Solution in C use function template
- Template lttypename Tgt
- void copy (T from, T to, int size)
- for( int i0 iltsize i)
- toi fromi
-
- int x10, y10
- double a5, b5
- copy( y, x, 10 ) // ok
- copy( b, a, 5 ) // ok
- copy( y, a, 5 ) // compile time error
- Here, type becomes a parameter. Same code can be
used for different types.
6- C function template prototype is any of the two
following ones - template ltclass identifiergt
function_declaration - template lttypename identifiergt function_declaratio
n
7- If the implementation of a set of functions
remains unchanged over a set of data type
instance, we can write a function template. - A template function starts with keyword template.
- In the previous example, T is a template type
parameter. It is a symbol serves as a placeholder
for a specific data type. - Keyword class and typename have the same meaning.
They are used to declare different template type
parameters.
8- If a function template has more than one template
type parameter, each type parameter must be
preceded by keyword class or typename. - Example
- template lttypename T, Ugt // Error !
- void f(T, U)
- template lttypename T, class Ugt // ok !
- T f(T, U)
9Function Template Instantiation
- To instantiate the template function
to construct individual functions given a set of
actual types or values. - templatelt typename T gt
- T largerOfTwo( T x, T y )
- return x gt y ? x y
-
- int main()
- int x1 0, y1 1
- cout ltlt the larger one is ' ltlt largerOfTwo(
x1, y1 ) ltlt endl
10Function Template Instantiation
- When a template function is called, the actual
parameters passed to the function are used to
determine which version of the template function
is constructed. - That is, the template type parameters are deduced
from the functions actual parameters, and an
appropriate function is constructed by the
compiler. - Different versions of largerOfTwo are constructed
by the compiler given different types of
parameters.
11- int main()
- int x1 0, y1 1
- double x2 0.8, y2 8.9
- char x3 'c', y3 'z'
- char s110, s220
- cout ltlt largerOfTwo( x1, y1 ) // int version
generated - cout ltlt largerOfTwo( x2, y2 ) // double version
generated - cout ltlt largerOfTwo( x3, y3 ) // char version
generated - largerOfTwo( x1, x2 ) // compile error x1 and x2
- // have different
types, a unification error.
12Illustration of template instantiation.
13- Example 1
- include ltiostreamgt
- using namespace std
- template lttypename Tgt
- T max( T array, int size )
- T max_val array0
- for ( int i1 iltsize i )
- if ( arrayi gt max_val )
- max_val arrayi
- return max_val
-
- int main()
- int a5 1, 4, 6, 7, 9
- double b4 2.3, 10.5, 34.7, 11.2
- cout ltlt "max of int array is " ltlt max( a, 5 )
ltlt endl - cout ltlt "max of double array is " ltlt max( b, 4
) ltlt endl -
14- A template can have non-type parameters. A
non-type parameter represents a constant value in
the template definition the value is also
deduced from the functions actual parameter.
15- Example 2 A modified version with non-type
template parameter added. - include ltiostreamgt
- using namespace std
- template lttypename T, int sizegt
- T max( T (array)size )
- T max_val array0
- for ( int i1 iltsize i )
- if ( arrayi gt max_val )
- max_val arrayi
- return max_val
-
- int main()
- int a 1, 4, 6, 7, 9
- double b4 2.3, 10.5, 34.7, 11.2
- cout ltlt "max of int array is " ltlt max( a ) ltlt
endl - cout ltlt "max of double array is " ltlt max( b )
ltlt endl
16- Function templates are not always appropriate for
all data types. - Example
- template lttypename Tgt
- void swap( T x, T y)
- T tmp
- tmp x
- x y
- y tmp
-
- int x, y
- char str110, str210
- char c
- double m, n
- char s1 str1, s2 str2
17- swap( x, y )
- swap( m, n )
- swap( x, m ) // error
- swap( str1, str2 ) // error. constant pointers
- swap( s1, s2 ) // legal but may not be intention
- We need to write a special case for swapping
strings. - void swap( char s1, char s2)
- // swap using library
function strcpy - // omitted
18Class Template
- Class template in C provides a powerful
mechanism for code reusability especially in the
implementation of data structures (vectors,
lists, trees, etc.) - class template class with
type parameter
19Class Template
- A int vector class
- class Vector
- public
- Vector() v(0), v_size(0)
- Vector(int n)
- Vector(Vector v)
- Vector()
- void assign()
- void display()
- private
- int v
- int v_size
20Class Template
- VectorVector(int n)
- v_size n
- v new intv_size
-
- void Vector display()
- cout ltlt "The vector is \n"
- for ( int i0 iltv_size i )
- coutltlt vi ltlt '\n'
-
- void Vectorassign()
- cout ltlt "Please input " ltlt v_size ltlt " values
\n" - for ( int i0 iltv_size i )
- cingtgtvi
-
- // rest omitted
21Class Template
- A double vector class
- class Vector
- public
- Vector() v(0), v_size(0)
- Vector(int n)
- Vector(Vector v)
- Vector()
- void assign()
- void display()
- private
- double v // change here
- int v_size
22Class Template
- VectorVector(int n)
- v_size n
- v new doublev_size // change here
-
- void Vector display()
- cout ltlt "The vector is \n"
- for ( int i0 iltv_size i )
- coutltlt vi ltlt '\n'
-
- void Vectorassign()
- cout ltlt "Please input " ltlt v_size ltlt " values
\n" - for ( int i0 iltv_size i )
- cingtgtvi
-
- // rest omitted
23Class Template
- Question
- Can we write the code for an Vector class only
once then use this code to create Vectors of any
data type ? - Answer
- Yes. We can make a class template Vector.
24Class Template Definition
- A class template has at least one type
parameter(class parameter). - A type parameter is a symbol serves as the
placeholder for a specific data type.
25Class Template Definition
- A definition and a declaration of a class
template always begins with keyword template. - Keyword template is followed by a template
parameter list. - The template parameter list can not be empty.
26Class Template Definition
- Example
- templatelt class T gt // or
templatelt typename T gt - class Vector
- public
- Vector() v(0), v_size(0)
- Vector(int n)
- Vector(Vector v)
- Vector()
- void assign()
- void displayObject()
- private
- T v
- int v_size
27Class Template Definition
- Defining member functions inside class
declaration - Example
- templatelt class T gt
- class Vector
- public
- Vector() v(0), v_size(0)
- Vector (int n)
- v_size n
- v new Tv_size
-
- // ...
28Class Template Definition
- If member functions are defined outside class
declaration, template header must be included in
front of each function definition.
29- Example
- templatelt class T gt
- class Vector
- public
- Vector() v(0), v_size(0)
- Vector (int n)
- Vector ()
- void assign ()
- void displayObject ()
- private
- T v
- int v_size
30- templatelt class T gt
- Vectorlt T gtVector(int n)
- v_size n
- v new Tv_size
-
- templatelt class T gt
- Vectorlt T gt Vector()
- delete v
-
- templatelt class T gt
- void Vectorlt T gt displayObject(void)
- for ( int i0 iltv_size i )
- coutltlt vi ltlt '\n'
-
- templatelt class T gt
- void Vectorlt T gtassign()
- for ( int i0 iltv_size i )
- cingtgtvi
- //...
31Template Instantiation
- To use a class template, we need to specify a
data type for the type parameter. - Vectorlt int gt v1 // create v1 as an integer
vector - Here,
- Vectorlt int gt
- is called a template instantiation, which is the
generation of a class from the generic class
template definition.
32Template Instantiation
- In this example, the data type int replaces the
type parameter T in Vectors declaration. That
is, the compiler replaces the occurrences of T in
Vectors declaration with int. - Example the line
- T v
- becomes
- int v
33Template classes, Classes and Objects
- An object can not belong to a class template, but
only to a class template instantiation.
34Template classes, Classes and Objects
- Objects of a class type that is an instantiation
of a class template are declared and used exactly
the same as objects of a non-template class type.
35Template classes, Classes and Objects
- We can have many instantiations for one template
class. - A template instantiation can be created with
either a built-in or user-defined type. - Example
- include "myclass.h"
- include "customer.h"
- // ...
- Vectorlt double gt v1
- Vectorlt float gt v2(10)
- Vectorlt Myclass gt v3
- Vectorlt customer gt customer_line
36Template Parameters
- A template class can have multiple type
parameters. - templatelt class T, class U gt
- class Sample
- // ...
-
- Samplelt int, int gt x
- Samplelt double, int gt y
37Template Parameters
- A template class can also have parameters that
are not type parameters. Those parameter are also
known as non-type parameters they are of
ordinary types such as ints. - templatelt class T, int SIZE gt
- class Vector
- // ...
-
- Vectorlt int, 5 gt x // vector of 5 ints
- Vectorlt double, 100 gt y // vector of 100 doubles
38Template Parameters
- A non-type parameter can be used to represent a
constant value in a class template definition it
must be passed a constant expression at
instantiation.
39Template Parameters
- Example (sam1.cpp)
- templatelt class T, int SIZE gt
- class Vector
- public
- // ...
- private
- T vSIZE
-
- Vectorlt double, 100 gt v1
- int a 1, 2, 3, 4
- Vectorlt int, sizeof( a )/sizeof( int ) gt v2
//? - int size
- cin gtgt size
- Vectorlt float, size gt v3 //?
40Default Template Parameters
- Template parameters can have default values.
- templatelt class T int, int SIZE 100 gt
- class Vector
- // ...
-
- Vectorlt double gt v1 // 100 doubles
- Vectorltgt v2 // 100 ints
41- Identify which, if any, of the following
instantiation are valid. - templatelt class T gt
- class Array // ...
-
- templatelt class T, int SIZE100 gt
- class List// ...
-
- include "card.h"
- //...
- Array a1
- Arraylt T gt a2
- Arraylt int gt a3
- Arraylt Card gt a4
- Listlt int, 10 gt l1
- Listlt Card gt l2
- Listlt 10 gt l3
- Arraylt int gt ptr
- Arraylt Listlt double gtgt complex_vector // ?
42Standard Template Library
- The Standard Template Library (STL) is an
important component of the C standard library. - The STL is a generic library that provides
solutions to managing of data with modern and
efficient algorithms.
43Standard Template Library
- STLs three basic components are
- Containers a collection of data structures.
- e.g. vector, queue, list ...
- Algorithms functions for processing the elements
of a container. - e.g. functions that copy, sort, search
containers. - Iterators are used to step through the elements
of containers. - e.g. we can use an iterator to move
through a list from front to end, from end to
front or randomly.
44Standard Template Library
- In STL, the data is managed by container classes
the operations are defined by algorithms. - Iterators link these two components they let
algorithms interact with containers.
45Containers
- STL containers are implemented as template
classes. There are two general kinds of
containers - Sequential containers are ordered collections in
which each element has a certain position. - Predefined sequential containers in STL
vector, list, deque - Associative containers are sorted collections in
which the actual position of an element depends
on its value due to a certain sorting criterion. - Predefined associative containers in STL
set, map, multiset, multimap
46STL Container Classes
47STL Container Classes
48Vectors
- A vector manages its elements in a dynamic array.
Random access of vector elements is enabled.
49- Example (sam3.cpp)
- include ltiostreamgt
- include ltvectorgt
- using namespace std
- int main()
- vectorlt int gt nums
- // append elements with value 0 to 5
- for ( int i0 ilt6 i )
- nums.push_back(i)
- for ( int i0 ilt nums.size() i )
- cout ltlt nums i ltlt ' '
- cout ltlt endl
- // remove first element
- nums.erase( nums.begin() )
- for ( int i 0 ilt nums.size() i )
- cout ltlt nums i ltlt ' '
- cout ltlt endl
50- Output
- 0 1 2 3 4 5
- 1 2 3 4 5
51Deques
- A deque ( double-ended queue ) is a dynamic array
that can grow in both directions.
52- Example (sam4.cpp)
- include ltiostreamgt
- include ltdequegt
- using namespace std
- int main()
- dequelt int gt nums
- // append elements with value 0 to 5
- for ( int i 0 ilt6 i )
- nums.push_back(i)
- for ( int i 0 ilt nums.size() i )
- cout ltlt nums i ltlt ' '
- cout ltlt endl
53- // insert at front with value 5 to 1
- for ( int i 1 i lt 6 i)
- nums.push_front(i)
- for ( int i 0 ilt nums.size() i )
- cout ltlt nums i ltlt ' '
- cout ltlt endl
-
Output 5 4 3 2 1 0 1 2 3 4 5
54Lists
- A list is implemented as a doubly linked list of
elements. Each element in a list has its
predecessor and its successor. Lists dont
provide random access.
55- Example (sam5.cpp)
- include ltiostreamgt
- include ltlistgt
- using namespace std
- int main()
- listlt int gt nums
- // append elements with value 0 to 5
- for ( int i0 ilt6 i )
- nums.push_back(i)
- // can NOT access list elements using operator
as follows - // for ( int i0 ilt nums.size() i )
- // cout ltlt nums i ltlt ' '
- // output and remove first element
- while( !nums.empty() )
- cout ltlt nums.front() ltlt ltltendl
- nums.pop_front() // removes the first element
-
-
56- Note
- Although ordinary arrays ( static or dynamic )
are not STL container class, STL algorithms can
be called on these arrays. - The library class string can be used as STL
containers. Strings are similar to vectors except
that their elements are characters.
57Associative containers
- Sets
- A set is a collection where elements are sorted
according to their own values. Each element may
occur only once. - Multisets
- A multiset is the same as set except that
duplicates are allowed.
58Associative containers
- Maps
- A map contains elements that are key/value pairs.
Each element has a key that is the basis for the
sorting criterion and a value. Each key may occur
only once. - Multimaps
- A multimap is the same as a map except that
duplicates are allowed.
59Associative containers
- Elements in associative containers are sorted.
- Random access of elements is not supported.
60Iterators
- An STL iterator can be viewed as a high-level
pointer used to navigate through elements in an
STL container. It has the following basic
operations - operator Returns the elements of current
position. - operator Moves to next element
- operator and ! Returns whether two
iterators represent the same position - operator Assignment
61Iterators
- These operators are exactly the same interface of
ordinary pointers. STL iterators are in fact
smart pointers that are used on more
complicated data structures of containers.
62Iterators
- All STL containers provide the same basic methods
to enable the use of iterators to navigate over
their elements. The most important two - begin() returns the position of the beginning of
the elements in the container. The beginning is
the position of the first element if the
container is not empty. - end() returns position of the end of the elements
in the container. The end is the position behind
the last element.
63Iterators
- Note
- Since begin() and end() define a half-open range,
we can simply check whether begin() equals end()
to decide whether a range is empty.
64Iterators
- All STL container classes have associated
iterator data types. e.g. the container listltintgt
has the associated iterator types - listlt int gtiterator
- listlt int gtconst_iterator
- The const iterator is used if the iteration does
not change any of the containers elements.
65Iterators
- STL iterators belong to two categories
- Bidirectional iterator they are able to iterate
in two directions. The iterators of the container
classes list, set, multiset, map and multimap are
bidirectional iterators. - Random access iterator they have all the
properties of bidirectional iterators and also we
can add or subtract offset on them, process
differences and compare with operator lt and gt.
The iterators of the container classes vector and
deque are random access iterators.
66Iterators
- Use iterators to access vector.
- Example (sam6.cpp)
- include ltiostreamgt
- include ltvectorgt
- include ltstringgt
- using namespace std
- int main()
- vectorlt string gt names
- names.push_back( "Jenny" )
- names.push_back( "Amy" )
- names.push_back( "Jessi" )
67Iterators
- vectorlt string gtiterator it
- for (it names.begin() it ! names.end() it
) - cout ltlt it ltlt endl
- // same effect. vector iterator is random
- // for (it names.begin() it lt names.end()
it ) - // cout ltlt it ltlt endl
Output Jenny Amy Jessi
68Iterators
- Use iterators to access lists.
- Example (sam7.cpp)
- include ltiostreamgt
- include ltlistgt
- include ltstringgt
- using namespace std
- int main()
- listlt string gt names
- names.push_back( "Jenny" )
- names.push_back( "Amy" )
- names.push_back( "Jessi" )
69Iterators
- listlt string gtiterator it
- for (it names.begin() it ! names.end() it
) - cout ltlt it ltlt endl
- // Won't work, since list iterator is not random
- // for (it names.begin() it lt names.end()
it ) - // cout ltlt it ltlt endl
Output Jenny Amy Jessi
70Iterators
- Use iterator to access sets.
- Example (sam8.cpp)
- include ltiostreamgt
- include ltsetgt
- include ltstringgt
- using namespace std
- int main()
- setlt string gt names
- // no push_back for associative containters
- // names.push_back( "Jenny" )
- names.insert("Jenny")
- names.insert("Amy")
- names.insert("Jessi")
- names.insert("Jeson")
71Iterators
- setlt string gtiterator it
- for (it names.begin() it ! names.end() it
) - cout ltlt it ltlt endl
-
Output Amy Jenny Jeson Jessi Note output is
sorted.
72Iterators
- Use iterator to access maps.
- Example (sam9.cpp)
- include ltiostreamgt
- include ltmapgt
- include ltstringgt
- using namespace std
- int main()
- map ltstring, float gt marks
- marks.insert( pairltstring, floatgt( "Jenny", 97
)) - marks.insert( pairltstring, floatgt( "Amy", 78.5
)) - marks.insert( pairltstring, floatgt( "Jessi", 86
)) - marks.insert( pairltstring, floatgt( "Jeson", 65 ))
73Iterators
- maplt string, float gtiterator it
- for (it marks.begin() it ! marks.end() it
) - cout ltlt it-gtfirst ltlt ' ' ltlt it-gtsecond ltlt endl
- it marks.find("Jenny")
- if ( it ! marks.end())
- cout ltlt "Found Jenny" ltlt endl
Output Amy 78.5 Jenny 97 Jeson 65 Jessi 86 Found
Jenny
74- Another example of map. (sam10.cpp)
- include ltiostreamgt
- include ltmapgt
- include ltstringgt
- using namespace std
- int main()
- mapltstring, intgt freq // map of words and their
frequencies - string word
- // read words from input stream
- while (cin gtgt word)
- freqword // can use subscript operator
-
- cout ltlt "Number of words " ltlt freq.size() ltlt
endl - mapltstring, intgtiterator it
- for (itfreq.begin() it ! freq.end() it)
- cout ltlt it-gtsecond ltlt " " ltlt it-gtfirst ltlt endl
-
75- Sample run
- gt a.out
- hello jenny
- hello tommy
- hi tommy
- welcome jenny
- Number of words 5
- 2 hello
- 1 hi
- 2 jenny
- 2 tommy
- 1 welcome
76Algorithms
- STL provides several standard algorithms for
processing elements of a container. - Four categories
- Sorting algorithms
- Non-mutating sequence algorithms
- Mutating sequence algorithms
- Numerical algorithms
- STL algorithms are implemented as template
functions they operate with iterators.
77Sorting Algorithms
- General sorting, merges, binary search, etc.
- Example
- The prototype for STLs sort algorithm which
sorts the elements in ascending order - templatelt class RandomIterator gt
- void sort( RandomIterator it1, RandomIterator it2
)
78Sorting Algorithms
- Usage 1
- vectorlt int gt v
- v.push_back( 45 )
- v.push_back( 10 )
- v.push_back( 24 )
- sort( v.begin(), v.end() )
- Usage 2
- string words4 "my", "favorite", "story",
"book" - sort( words0, words4 )
- sort( words, words 4 )
- Ordinary arrays can be used with STL algorithms
and treated as random-access containers.
79Non-mutating sequence algorithms
- Non-mutating algorithms dont modify the contents
of the container. E.g. search a container for a
particular element and return its position.
80Mutating sequence algorithms
- Mutating algorithms can modify the contents of
the container. E.g. replace certain elements of a
container.
81- Example (sam11.cpp)
- include ltiostreamgt
- include ltvectorgt
- include ltalgorithmgt
- using namespace std
- void dump( int i ) cout ltlt i ltlt "\n"
- bool odd( int i ) return i 2 ! 0
- bool comp( int i1, int i2 ) return i1 gt i2
- int main()
- vectorlt int gt v
- v.push_back( 45 )
- v.push_back( 10 )
- v.push_back( 24 )
- vectorltintgtiterator iter
- iter find( v.begin(), v.end(), 10 )
//non-mutating sequence algorithm - replace_if( v.begin(), v.end(), odd, 1 )
//mutating sequence algorithm - sort( v.begin(), v.end(), comp )
- for_each( v.begin(), v.end(), dump ) // 24, 10,
1 - sort( v.begin(), v.end() )
82Use STL to write reusable code
- Example
- int count( vectorlt char gt v, char comp )
- int count 0
- vectorltchargtiterator iter
- for( iter v.begin() iter ! v.end() iter )
- count (comp iter)
- return count
-
83Use STL to write reusable code
- A more general version
- templateltclass InIteratorgt
- int count( InIterator begin, InIterator end, char
comp) - int count 0
- for( begin ! end begin )
- count (comp begin)
- return count