Download presentation
Presentation is loading. Please wait.
1
Templates and Standard Containers
Chapter 6
2
Templates Templates allow functions and classes to be parameterized
type of data being operated upon (or stored) is received via a parameter. Templates provide a means to reuse code One template definition can be used … to create multiple instances of a function (or class), each operating on (storing) a different type of data. The template mechanism is important and powerful. It is used throughout the Standard Template Library (STL) to achieve genericity.
3
Templates
4
Functions Rationale for functions:
Make pieces of code reusable Encapsulating them within a function. Consider the task of swapping the values stored in two variables void Swap (int & first, int & second) { int temp = first; first = second; second = temp; }
5
Integer Solution Function Swap gives a general solution to the interchange problem for ints This Swap function can be used to exchange the values of any two integer variables In contrast, inline code would have to be rewritten for each pair of integer variables to swap.
6
Swap for Doubles To interchange the values of two double variables:
Can't use the preceding function; it swaps ints Overloading allows us to define multiple versions of the same function: void Swap (double & first, double & second) Different Swap functions are distinguished by the compiler according to a function's signature name, number, type and order of parameters
7
Swap for Strings To interchange the values of two string variables:
Again, overload function Swap(): void Swap(string & first, string & second) { string temp = first; first = second; second = temp; }
8
Swap Library Why not create a library of all possible types to swap
Would work for predefined C++ types but not for user defined types must overload for each user defined type void Swap(Time & first, Time & second) { Time temp = first; first = second; second = temp; }
9
Observations The logic for each version of the Swap function is exactly the same The only difference is in the type of the values being exchanged Consider passing the type as a parameter! Write a general solution Could be used to exchange two values of any type
10
Template Mechanism Declare a type parameter
also called a type placeholder Use it in the function instead of a specific type. This requires a different kind of parameter list: void Swap(______ & first, ______ & second) { ________ temp = first; first = second; second = temp; }
11
Template Mechanism The word template is a C++ keyword
Specifies that what follows is … a pattern for a function not a function definition. “Normal” parameters (and arguments) appear within function parentheses Type parameters (and arguments for class templates) appear within template angle brackets (< > ).
12
Template Mechanism A function template cannot be split across files
specification and implementation must be in the same file A function template is a pattern describes how specific functions is constructed constructed based on given actual types type parameter said to be "bound" to the actual type passed to it
13
Template Mechanism Each of the type parameters must appear at least once in parameter list of the function compiler uses only types of the arguments in the call thus determines what types to bind to the type parameters
14
Function Template template <typename ElementType>
void Swap (ElementType &first, ElementType &second) { ElementType hold = first; first = second; second = hold; }
15
Function Template template <typename ElementType>
void Swap (ElementType &first, ElementType &second) Originally, the keyword class was used instead of typename in a type-parameter list. "class" as a synonym for "kind" or "category"— specifies "type/kind" of types.
16
Function Template <typename ElementType> names ElementType as a type parameter The type will be determined … by the compiler from the type of the arguments passed when Swap() is called.
17
General Form of Template
template <typename TypeParam> FunctionDefinition or template <class TypeParam> FunctionDefinition where: TypeParam is a type-parameter (placeholder) naming the "generic" type of value(s) on which the function operates FunctionDefinition is the definition of the function, using type TypeParam.
18
Template Instantiation
A function template is only a pattern describes how individual functions can be built from given actual types. This process of constructing a function is called instantiation. In each instantiation, the type parameter is said to be bound to the actual type passed. A template thus serves as a pattern for the definition of an unlimited number of instances.
19
Template Instantiation
In and of itself, the template does nothing. When the compiler encounters a template it stores the template but doesn't generate any machine instructions. Later, when it encounters a call to Swap() Example: Swap(int1, int2); it generates an integer instance of Swap()
20
Template Instantiation
Algorithm for instantiation Search parameter list of function template for type parameters. If one is found, determine type of corresponding argument. Bind these types. The compiler must actually "see" the definition of the function not just the prototype thus the requirement – a function template cannot be split across two files
21
Programming Style Tip For efficiency (and often correctness), compilers frequently recommend: Explicit instantiation: Provide a prototype of function to be later instantiated to the compiler. void Swap(int, int); void Swap(double, double); void Swap(string, string); void Swap(Time, Time);
22
Exercise Write a function template which will find the largest element in an array Write a driver program which will test this with at least three different instantiations Apply concepts and tips presented in the lecture
23
Templates With Multiple Parameters
Given: template <typename Type1, typename Type2 > void whatEver (Type1, Type2){ … } Each type parameter must appear at least once in the function's parameter list. Compiler must be able to determine actual type corresponding to each type parameter from a function call. Why?
24
Templates With Multiple Parameters
Example template <typename Type1, typename Type2> void Convert(Type1 value1, Type2 & value2) { value2 = static_cast<Type2>(value1); } What does this function do? Write a driver program to try it out
25
Templates With Multiple Parameters
The following version of function template Convert would not be legal … Why?? template <typename Type1, typename Type2> Type2 Convert(Type1 value1) { return static_cast<Type2>(value1); } Type2 is not in the parameter list
26
Solution We could provide a dummy second parameter indicating the type of the return value: template <typename Type1, typename Type2> Type2 Convert(Type1 value1, Type2 value2) { return static_cast<Type2>(value1); } Function call: double x = 3.14; int ix = Convert(x, 0);
27
Another Solution #include <iostream> using std::cout; using std::endl; template<typename type1, typename type2> type1 convert(type2 value) { return static_cast<type1>(value); } int main() { float pi= F; cout << convert<int>(pi) << endl; }
28
Class Templates Recall our Stack class:
const int STACK_CAPACITY = 128; typedef int StackElement; class Stack { /***** Function Members *****/ public: . . . /***** Data Members *****/ private: StackElement myArray[STACK_CAPACITY]; int myTop; }; How did we create a new version of a stack for a different type of element?
29
What’s wrong with typedef?
To change the meaning of StackElement Merely change the type following typedef Problems: Changes the header file Any program that uses this must be recompiled A name declared using typedef can have only one meaning. What if we need two stacks of different types in the same program? cannot overload like functions (same number, type, and order of parameters)
30
Type-Independent Container
Use a class template: the class is parameterized it receives the type of data stored in the class via a parameter (like function templates). Recall const int STACK_CAPACITY = 128; __________________________________ class Stack { /***** Function Members *****/ public: /***** Data Members *****/ private: StackElement myArray[STACK_CAPACITY]; int myTop; }; template <typename StackElement> StackElement is a “blank” type (a type placeholder) to be filled in later.
31
General Form Of Class Template Declaration
template <typename TypeParam > or template <class TypeParam> class SomeClass { // ... members of SomeClass }; More than one type parameter may be specified: template <typename TypeParam1,..., typename TypeParamn> class SomeClass { // ... members of SomeClass ... };
32
Instantiating Class Templates
Instantiate it by using declaration of form ClassName<Type> object; Passes Type as an argument to the class template definition. Examples: Stack<int> intSt; Stack<string> stringSt; Compiler will generate two distinct definitions of Stack two instances one for ints and one for strings.
33
Rules For Class Templates
Definitions of member functions outside class declaration must be function templates. All uses of class name as a type must be parameterized. Member functions must be defined in the same file as the class declaration.
34
Applying the Rules to Our Stack Class
Recall how we specified the prototypes in the class Used StackElement Thus no changes needed – all rules OK Apply Rule 1 Each member functions definition preceded by template <typename StackElement>
35
Applying the Rules to Our Stack Class
Apply Rule 2 The class name Stack preceding the scope operator (::) is used as the name of a type must therefore be parameterized. template <typename StackElement> void Stack<StackElement>::push(const StackElement & value) { /* ... body of push() ... */ } Apply Rule 3 : specification, implementation in same file
36
Applying the Rules to Friend Functions
Consider the addition of a friend function operator<< Second parameter is of type Stack, must parameterized friend ostream & operator<<(ostream & out, const Stack<StackElement>& st);
37
Applying the Rules to Friend Functions
When defining the operator<< function It must be defined as a function template template<typename StackElement> ostream & operator<<(ostream & out, const Stack<StackElement> & st) { }
38
Exercise Work together to complete a template version of the class Queue Write a driver program to test it Use at least three different types
39
STL (Standard Template Library)
A library of class and function templates Components: Containers: Generic "off-the-shelf" class templates for storing collections of data Algorithms: Generic "off-the-shelf" function templates for operating on containers Iterators: Generalized "smart" pointers that allow algorithms to operate on almost any container
40
Standard Template Library
Example of a specific container class iterator algorithm vector sort() begin() end()
41
STL's 10 Containers Kind of Container STL Containers
Sequential: deque, list, vector Associative: map, multimap, multiset, set Adapters: priority_queue, queue, stack Non-STL: bitset, valarray, string
42
The vector Container A type-independent pattern for an array class
capacity can expand self contained Declaration template <typename T> class vector { } ;
43
The vector Container Constructors vector<T> v, // empty vector
v1(100), // 100 elements of type T v2(100, val), // 100 copies of val v3(fptr,lptr); // contains copies of // elements in memory // locations fptr to lptr
44
The vector Container Vector operations See table on pg 270
Vector object treated much like an array without limitations of C-style arrays Note how vector objects are self contained able to manipulate their own "stuff"
45
Iterators Note from table that a subscript operator is provided
BUT … this is not a generic way to access container elements STL provides objects called iterators can point at an element can access the value within that element can move from one element to another They are independent of any particular container … thus a generic mechanism
46
Iterators Given a vector which has had values placed in the first 4 locations: v.begin() will return the iterator value for the first slot, v.end() for the next empty slot vector<int> v 9 4 15 3 v.begin() v.end()
47
Iterators Each STL container declares an iterator type
can be used to define iterator objects To declare an iterator object the identifier iterator must be preceded by name of container scope operator :: Example: vector<int>:: vecIter = v.begin()
48
Iterators Basic operators that can be applied to iterators:
increment operator ++ decrement operator -- dereferencing operator * Assignment = Addition, subtraction +, -, +=, -= vecIter + n returns iterator positioned n elements away Subscript operator [ ] vecIter[n] returns reference to nth element from current position
49
Iterators Contrast use of subscript vs. use of iterator
for (vector<double>::iterator it = v.begin(); it != v.end(); it++) out << *it << " "; ostream & operator<<(ostream & out, const vector<double> & v) { for (int i = 0; i < v.size(); i++) out << v[i] << " "; return out; }
50
Iterator Functions Note table on pages 286, 287
Note the capability of the last two groupings Possible to insert, erase elements of a vector anywhere in the vector Must use iterators to do this Note also these operations are inefficient for arrays due to the shifting required
51
Contrast Vectors and Arrays
Capacity can increase A self contained object Is a class template Has function members to do tasks Fixed size, cannot be changed during execution Cannot "operate" on itself Must "re-invent the wheel" for most actions
52
STL’s stack Container Actually, it is an adapter,
one of its type parameters is a container type. Sample declaration: stack<int, vector<int> > st; A class that acts as a wrapper around another class, provides a new user interface for that class. Note: errors in text: pp. 299 & 301
53
Container Adapters A container adapter such as stack
Uses the members of the encapsulated container To implement what looks like a new container. For a stack<T, C<T> > C<T> may be any container that supports push_back() and pop_back() in a LIFO manner. In particular C may be a vector, a deque, or a list
54
STL’s stack Container Constructor stack< T, C<T> > st;
The space between the two >s must be there to avoid confusing the compiler (else it treats it as >>); Constructor stack< T, C<T> > st; creates an empty stack st of elements of type T uses a container C<T> to store the elements. The default container is deque; if C<T> is omitted as in stack<T> st; a deque<T> will be used to store the stack elements.
55
STL's queue Container In queue<T, C<T> >, container type C may be list or deque. Why not vector? It can't remove from the front efficiently! The default container is deque.
56
STL's queue Container queue has same member functions and operations as stack except: push() adds item at back (our addQ()) front() (instead of top()) retrieves front item pop() removes front item (our removeQ()) back() retrieves rear item
57
deques As an ADT, a deque is a double-ended queue
It is a sequential container Acts like a queue (or stack) on both ends It is an ordered collection of data items Items can only be added or removed at the ends
58
deques Basic operations Construct a deque (usually empty):
Check if the deque is empty Push_front: Add an element at the front of the deque Push_back: Add an element at the back of the deque
59
deques Basic operations (ctd.) Front: Back: Pop_front: Pop_back:
Retrieve the element at the front of the deque Back: Retrieve the element at the back of the deque Pop_front: Remove the element at the front of the deque Pop_back: Remove the element at the back of the deque
60
STL's deque Class Template
Has the same operations as vector<T> except … there is no capacity() and no reserve() Has two new operations: d.push_front(value); Push copy of value at front of d d.pop_front(value); Remove value at the front of d
61
STL's deque Class Template
Like STL's vector, it has several operations that are not defined for deque as an ADT: [ ] subscript operator insert and delete at arbitrary points in the list, same kind of iterators. But: insertion and deletion are not efficient in fact, take longer than for vectors.
62
vector vs. deque vector deque Capacity of a vector must be increased
It must copy the objects from the old vector to the new vector It must destroy each object in the old vector A lot of overhead! With deque this copying, creating, and destroying is avoided. Once an object is constructed, it can stay in the same memory locations as long as it exists If insertions and deletions take place at the ends of the deque.
63
vector vs. deque Unlike vectors, a deque isn't stored in a single varying-sized block of memory, but rather in a collection of fixed-size blocks (typically, 4K bytes). One of its data members is essentially an array map whose elements point to the locations of these blocks.
64
Storage for A deque Example: a deque with 666, 777, 888, 6, 5 in this order, from front to back When a data block gets full, a new one is allocated and its address is added to map.
65
Storage for A deque When map gets full, a new one is allocated
The current values are copied into the middle of it. Inserts and deletes may involve cross- block element-shifting!
66
Bitsets The C++ standard includes bitset as a container,
but it is not in STL. A bitset is an array whose elements are bits. Much like an array whose elements are of type bool, Unlike arrays, bitset provides operations for manipulating the bits stored in it. They provide an excellent data structure to use to implement sets.
67
ValArrays The standard C++ library also provides the valarray class template, Designed to carry out (mathematical) vector operations very efficiently. Highly optimized for numeric computations.
68
STL's Algorithms STL has a collection of more than 80 generic algorithms. not member functions of STL's container classes do not access containers directly. They are stand-alone functions operate on data by means of iterators . Makes it possible to work with regular C-style arrays as well as containers.
69
Example of sort Algorithm
#include <iostream> #include <algorithm> using namespace std; int main() { int ints[] = {555, 33, 444, 22, 222, 777, 1, 66}; sort(ints, ints + 8); cout << "Sorted list of integers:\n"; Display(Ints, 8); } Must supply start and "past the end" pointers Note use of template function
70
Display Note the Display function template used by the previous program template <typename ElemType> void Display(ElemType arr, int n) { for (int i = 0; i < n; i++) cout << arr[i] << " "; cout << endl; }
71
Another Version of sort()
Define your own "less than" function bool DubLessThan(double a, double b) { return a > b; } // ??? Call the sort function, specifying this as the function to be used for comparison double dubs[] = {55.5,3.3,44.4,2.2,22.2,77.7,0.1}; sort(dubs, dubs + 7, DubLessThan); Output !! Name of function is a pointer const to code
72
Creating a < Operator for Use by sort()
Consider defining < for two stacks as a comparison of the top element of each template <typename StackElement> bool operator<(const Stack<StackElement> & a, const Stack<StackElement> & b) { return a.top() < b.top();}
73
Creating a < Operator for Use by sort()
int main() { vector< Stack<int> > st(4); // vector of 4 stacks of ints st[0].push(10); st[0].push(20); st[1].push(30); st[2].push(50); st[2].push(60); st[3].push(1); st[3].push(999); st[3].push(3); sort(st.begin(), st.end()); for (int i = 0; i < 4; i++) cout << "Stack " << i << ":\n"; st[i].display(); cout << endl; } Output Stack 0: 3 999 1 Stack 1: 20 10 Stack 2: 30 Stack 3: 60 50
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.