Templates and the STL
Template (generic) classes the behavior of a container class does not depend of the kind of elements stored in the container how can we create a generic (type independent) collection class using C++? drawbacks of typedef have to change source code (recompile) for each type can’t have multiple containers whose elements are of different types an alternative: define a class template template for creating a class
Function templates template - a pattern or a mold functions/methods have data parameters void f (int p1, float p2, Customer p3); argument provided when function is called function templates also have type parameters from one function template multiple actual functions can be generated (by the compiler) allow a programmer to write "generic" functions - type independent
overloaded Swap differ only in the type! void Swap(int & first, int & second) { int temp = first; first = second; second = temp; } differ only in the type! void Swap(string & first, string & second) { string temp = first; first = second; second = temp; }
generic Swap template <typename Item> void Swap(Item & first, Item & second) { Item temp = first; first = second; second = temp; } 1. Swap is a function template 2. Item is a type parameter 3. keyword typename and class are interchangeable 4. template function prototype and definition must be in the same file 5. actual type substituted for Item must be "assignable"
Function instantiation no object code is created from a function template compiler generates object code for an actual function from a function template when needed when compiling a call to the function substitutes argument type for the type parameter each call with a different argument type results in object code for a new actual function Swap(i, j); // i and j are ints - Item replaced by int Swap(s1, s2); // s1 and s2 are strings - Item replaced by string etc.
Class templates make it possible to have several objects of a container class, each of which holds a different type of element Stack of ints; Stack of strings; Stack of ? declaration and implementation of a template class have to be compiled together template class implementation requires "messy" syntax
Class template for Stack template < typename SE > class Stack { public: - - - Stack ( ); void push (const SE & newElement); SE top ( ) const; private: SE myArray[STACK_CAPACITY]; int myTop; }; template directive Class name is Stack<SE>
declaring Stack<SE> objects int main ( ) { Stack <int> samples; Stack <float> cost; Stack <string> names; Stack <customer> line; - - -
implementing a template class cumbersome syntax needed each method is a template so is preceded by the template directive class name is Stack<SE> template <typename SE> Stack<SE>::Stack( ) { - - - - }
Compiling template classes compiler cannot separately compile a template class compiler needs to know the actual type to substitute compiler generates code when a template class object is declared substitutes actual type for the type parameter needs access to the class implementation, not just the class declaration compiler generates separate code for each actual type substituted for the type parameter
Two solutions Client.cpp Client.cpp stack.h stack #include “stack” #include “stack.h” client program client program stack.h stack Stack template class declaration Stack template class declaration followed by implementation #include “stack.cpp” stack.cpp implementation
Standard Template Library (STL) is a library of generic container classes which are both efficient and functional C++ STL developed in early 90's at Hewlett Packard Laboratories Alex Stepanov and Meng Lee became part of C++ standard in 1994 implementations available by late 90's see web page for STL Programmer's Guide
STL and Reuseability STL is part of a movement toward libraries of reusable code function libraries (reusable algorithms) class libraries (reusable ADTs) Java 1.2 introduced a library of Collection classes http://java.sun.com/docs/books/tutorial/ index.html data and algorithms packaged together (O-O) STL separates data and algorithms iterators allow algorithms to operate on data
STL components Containers Algorithms Iterators Container classes templates for classes which hold a collection of elements Algorithms templates for functions which operate on a range of elements from a container range is specified by iterators Iterators give access to the elements in a container allow for movement from one element to another Container classes Algorithms Iterators
STL container classes Sequences - elements arranged in a linear order vector<T> - fast inserts only at the end; random access list<T> - fast inserts anywhere; no random access deque<T> - fast inserts at the beginning and the end Adapters - provides a new interface (set of operations) for one of the sequences stack<T> ex: stack<int> operands; queue<T> ex: queue<Customer> line; priority_queue<T> Associative Containers - elements have key values set, map, multiset, multimap
vector<T> growable, self-contained, type-independent array element type specified when a vector is declared vector<double> numbers; vector<cashier> checkOutStations; has a set of operations (methods) capacity increases when needed some vectors vector<int> v1; (capacity is 0) vector<float> v2 (10); (capacity is 10; size is 10) vector<string> v3 (5, "C++"); (capacity is 5; size is 5)
Some vector<T> methods V.capacity( ) //size of array currently allocated V.size( ) //number of values V contains V.empty( ) //true iff V.size( ) is 0 V.reserve(n) //grow V so its capacity is n V.push_back(val) //add val at end of V V.pop_back( ) //erase V's last element V[i] //access element of V whose index is i V.at(i) //access element of V whose index is i
#include <iostream> #include <vector> using namespace std; bool Search(const vector<int> & V, int item); int main ( ) { vector<int> numbers; int number; while (cin >> number) { // enter <control> D to stop the loop if (Search(numbers, number)) cout << "Duplicate" << endl; else numbers.push_back(number); } cout << "number of unique values: " << numbers.size( ); return 0; bool Search(const vector<int> & V, int item) { int p = 0; while(p < V.size( ) ) if (item = = V[p]) // or V.at(p) return true; else p++; return false;
STL iterators iterators are "pointer-like" objects provide a generic way to access the elements of any container class many STL algorithms require iterators as arguments some STL algorithms return an iterator each STL container class has an iterator class associated with it vector<T>::iterator list<T>::iterator stack<T> and queue<T> don't have iterators why?
Iterator categories category determines available operations forward iterator iter++ (increment) *iter (dereference) == and != (equality comparison) bidirectional iterator adds iter-- (decrement) random-access iterator adds iter[n] (constant time access to arbitrary element) iter =+ n (increment n times)
STL Algorithms are function templates designed to operate on a sequence of elements rather than methods the sequence is designated by two iterators most container classes have the following two methods begin( ) - returns an iterator positioned at the container's first element end( ) - returns an iterator positioned past the container's last element (past-the-end) C.begin( ), C.end( ) specifies a sequence which contains all elements of the container C
STL Algorithms some examples of STL algorithms find (iter1, iter2, value) //returns an iterator max_element (iter1, iter2) //returns an iterator sort (iter1, iter2) //sorts using < for_each (iter1, iter2, F) //applies F to every //item see STL Programmer's Guide link on home page
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main ( ) { vector<int> numbers; int number; while (cin >> number) if (find (numbers.begin ( ), numbers.end ( ), number) != numbers.end ( )) cout << "Duplicate" << endl; else numbers.push_back(number); } cout << "number of unique values: " << numbers.size( ); return 0;
Press any key to continue #include <iostream> #include <vector> #include <algorithm> #include <cstdlib> using namespace std; void set (int & val); void display (int val); int main( ) { vector<int> A(5); for_each (A.begin ( ), A.end ( ), set); // would not work if vector<int> A; used for_each (A.begin ( ), A.end ( ), display); cout << endl; sort (A.begin ( ), A.end ( )); // operator< must be defined for A's element type return 0; } void set (int & val) { val = rand ( ); void display (int val) { cout << " " << val; 41 18467 6334 26500 19169 41 6334 18467 19169 26500 Press any key to continue
list<T> class another STL container class used for storing a linear collection of like items comparison to a vector? linked list vs array is the underlying data structure no indexing (iterators are bidirectional) inserts and deletes anywhere are done in a constant amount of time
a list<T> data structure head size ------ 2
Basic list class methods list( ); // construct an empty list list (const list<T> & aList); // copy constructor ~list( ); // destructor list<T> operator= (const list<T> & aList); // assignment operator bool empty( ); int size( );
Some more list methods L.push_back(value) // append value to L L.push_front(value) // insert value at front of L L.insert(pos, value) // insert value into L at // position indicated by iterator pos L.front( ) // return L's first element L.back( ) // return L's last element L.begin( ) // return an iterator positioned at start L.end( ) // return the"past the end" iterator L.sort( ) // sort L's elements using < Why not sort (L.begin( ), L.end( )); ?
#include <list> #include <iostream> using namespace std; int main ( ) { list<int>L; L.push_back (9); L.push_back (7); L.push_back (5); L.push_back (3); list<int>::iterator p; for (p = L.begin ( ); p != L.end ( ); p++) cout << *p << endl; (*p)++; return 0; } 9 7 5 3 10 8 6 4 Press any key to continue