300 likes | 421 Views
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
E N D
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 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; }
template <typename Item> void Swap(Item & first, Item & second) { Item temp = first; first = second; second = temp; } generic Swap 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"
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. 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
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
template directive 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; }; 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 #include “stack” #include “stack.h” client program e.g.; main 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
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
Container classes Algorithms Iterators STL components • Containers • 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
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
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; }
#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; }
41 18467 6334 26500 19169 41 6334 18467 19169 26500 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 for_each (A.begin ( ), A.end ( ), display); cout << endl; return 0; } void set (int & val) { val = rand ( ); } void display (int val) { cout << " " << val; }
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( )); ?
9 7 5 3 10 8 6 4 Press any key to continue #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; for (p = L.begin ( ); p != L.end ( ); p++) (*p)++; for (p = L.begin ( ); p != L.end ( ); p++) cout << *p << endl; return 0; }