1 / 39

EE4E. C++ Programming

EE4E. C++ Programming. Lecture 5 Templates and the Standard Template Library (STL). Contents. Introduction Function templates Class templates Creating function templates from class templates The Standard Template Library (STL). Introduction. Templates are a powerful feature of C++

pello
Download Presentation

EE4E. C++ Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. EE4E. C++ Programming Lecture 5 Templates and the Standard Template Library (STL)

  2. Contents • Introduction • Function templates • Class templates • Creating function templates from class templates • The Standard Template Library (STL)

  3. Introduction • Templates are a powerful feature of C++ • They allow the programmer to specify with a single code segment an entire range of related functions or classes • For example we might write a sort() function template able to sort ints, floats, chars and programmer defined classes • We might write a linked list class template able to handle many different data types • The Standard Template Library is a sophisticated set of class templates enabling us to use generalized container classes

  4. Function templates • Function templates are useful if we want to perform identical operations on different types of data • Examples would include searching and sorting arrays of different data types • The algorithms used would be the same for all data types • Only object equality and relational tests would differ

  5. Function template definitions begin with the template keyword • A list of formal type parameters follows in angle (< and >) brackets • template <class T>function_name • template <class A, class B> function_name • The function template is instantiated by specifying actual types (which can be primitive types or user defined types) in place of the formal types

  6. Example • A function template printArray() that prints the contents of an array of any instantiated type template class<T> void printArray(const T* array, const int count) { for (int i=0; i<count; i++) { cout << array[i] << “ “; cout << “\n”; } }

  7. void main() { const int n=5; int intArray[n]={1,2,3,4,5}; float floatArray[n]={1.0,2.0,3.0,4.0,5.0}; char charArray[n]=“Hiya”; printArray(intArray,n); printArray(floatArray,n); printArray(charArray,n); }

  8. The compiler in this case instantiates the following printArray() functions • printArray(const int*, const int) • printArray(const float*, const int) • printArray(const char*, const int) • No runtime overhead is involved • If T is replaced by a programmer defined type (such as Date), then the complier will look for a overloaded operator<<() function

  9. void main() { const int n=5; Date d(1,1,1990); Date* DateArray=new Date[n]; for (int i=0; i<n; i++) DateArray[i]=d++; // operator<<(ostream& os, const Date& d) called here printArray(DateArray,n); }

  10. Class templates • Class templates enable reusable data types to be easily created • Often called generic programming • For example we can create a generic stack (a last in first out data structure) using class templates • The generic stack can be instantiated with any data type • Stack of integers, stack of doubles, stack of dates etc

  11. // Stack class template template <class T> class Stack { private: int size; // No. of elements in the stack int top; // Location of the top element T* stackPtr; // Pointer to the stack public: Stack(int); ~Stack() { delete[] stackPtr; } int push(const T&); // Push an element int pop(T&); // Pop an element int isEmpty() { return top==-1;} int isFull() { return top==size-1;} };

  12. template<class T> Stack<T>::Stack(int a) { size=a; top=-1; // Initially empty stackPtr=new T[size]; // Allocate memory } template<class T> int Stack<T>::push(T& val) { if (!isFull()) { stackPtr[++top]=val; return 1; } return 0; } template<class T> int Stack<T>::pop(T& val) { if (!isEmpty()) { val=stackPtr[top--]; return 1; } return 0; }

  13. void main() { Stack<char> charStack(7); char[] name=“Michael”; int j=0; while(charStack.push(name[j]) j++; char c; cout << “My name in reverse is : “; while(charStack.pop(c)) cout << c; }

  14. This code assumes that an overloaded assignment operator function exist for programmer defined data types • This must be provided if the object used with the Stackclass contains dynamically allocated memory

  15. Creating function templates from class templates • We can easily create a function template by passing a class template as an argument to a function • A classic example is a sort() function template which sorts the contents of a container template (for example and array) passed as an argument

  16. template <class T> class Vector { private: T* v; int size; public: Vector(int) ; // Constructor int getSize( ) { return size; } T& operator[] (int ); // overloaded [] }; • We can demonstrate this by first creating a simple Vector template (like an array)

  17. template<class T> void sort(Vector<T>& v) { // sort the elements of v into increasing // order using a bubble sort int size=v.getSize(); for (int i=0; i<size-1; i++) for (int j=size; i<j; j--) if (v[j]<v[j-1]) // swap v[j] & v[i] { T t = v[j]; v[j]=v[j-1]; v[j-1] = t; } } • We can then create a sort() function template

  18. void main() { Vector<int>& vi(100); Vector<char*>& vc(100); Vector<float>& vf(100); Vector<Circle>& vci(100); // initialize the vectors // ….. . sort(vi); sort(vc); sort(vf); sort(vci); }

  19. The compiler will try and create the correct sort() functions by instantiating the templated functions • It will run into 2 problems in this example • Instantiating sort() with a char* (a string) argument will produce incorrect results • The ‘<‘ operator will not test for alphabetical ordering of the strings • Instantiating sort() with a Circle object argument will produce a compilation error • We need an overloaded operator<() function defined on Circle objects

  20. We can create sort() functions for specific datatypes that will override the instantiated function template<class T> void sort(Vector<char*>& v) { // sort the elements of v into increasing // order using a bubble sort int size=v.getSize(); for (int i=0; i<size()-1; i++) for (int j=size()-1; i<j; j--) if (strcmp(v[j],v[j-1])<0) { T t = v[j]; v[j]=v[j-1]; v[j-1] = t; } }

  21. We can also create an operator<() function for Circle objects int operator < (Circle& c1,Circel& c2) { return c1.radius<c2.radius; }

  22. Other features of templates • Templates and friends • With templates, friendship can be established between either a class template or a particular instantiation of the template and global/member functions or entire classes • A few examples will clarify this:

  23. template<class T> class X { …. friend void f(); …. } • Declare a function f() to be a friend of every class specialization of class template X • Declare every member function of class Y to be a friend of every class specialization of class template X template<class T> class X { …. friend class Y; …. }

  24. Declare a function f(X<T>) to be a friend of class specialization X<T> for any T (such as float) • Declare every member function of class specialization Y<T> to be a friend of class specialization X<T> for any T (such as float) template<class T> class X { …. friend void f(X<T> &); …. } template<class T> class X { …. friend class Y<T>; …. }

  25. The Standard Template Library (STL) • The Standard Template Library (STL) is an addition to the C++ Standard Library • Developed at the Hewlett-Packard Labs in the mid-late 90’s • STL defines powerful, template-based, reuseable components that implement many common data structures and algorithms to process those data structures • STL is extremely complex, being optimised for efficiency. We will only scratch the surface

  26. STL is based on 3 components • Containers • Iterators • Algorithms • Template-based containers are data structures used to group objects of any type • Examples include linked lists, vectors and sets • Iterators encapsulate the mechanisms used to access container elements • A simple pointer can be used as an iterator for a standard array

  27. Algorithms are functions that perform common manipulations on containers • Examples include searching and sorting algorithms • There are around 70 algorithms implemented in the STL • A key aspect of the STL is that an algorithm can be applied to a container without regard to the exact implementation of the container • The container’s iterator just has to support the minimum requirement of the algorithm • This means that programmers can write one algorithm which can be applied to multiple containers

  28. Containers • Containers divided into 3 main categories • Sequence containers • Essentially linear data structures • Associative containers • Can be searched quickly using name/value pairings • Container adapters • Stacks, queues and priority queues

  29. Examples of sequence STL containers include • vector • Provides random access with constant time insertions and deletions at the end • deque (double entry queue) • Provides random access with constant time insertions and deletions at the beginning and the end • list • Provides linear time access but constant time insertions and deletions at any position in the list

  30. Examples of associative STL containers include • set • Provides rapid lookup (set membership), no duplicates around • multiset • Asabove but allows duplicates

  31. Iterators • Iterators allow generic algorithms to ‘plug in’ to different containers • As long as the container supports the iterator that the algorithm uses to access container elements, the algorithm can be applied to it

  32. Container Iterator Algorithm vector sort find list

  33. There are different classes of iterator to support things like linear or random access • However, certain iterator operations are uniform and can be applied to all containers • * (de-referencing) allows access to the element to pointer to by the iterator • ++ (increment) moves the iterator to the next element • begin() points the iterator at the first element • end() points the iterator at the last element

  34. Generally speaking, we have the following sub-division of iterators and associated containers • Sequence containers vector, deque • Random access iterators • Sequence container list • Linear bidirectional iterator • Associative containers set, multi-set, map, multi-map • Linear bidirectional iterator • No iterators supported for stack, queue, priority queue

  35. Iterator operations • Depends on iterator type • A few examples • ++p, p++,--p, p--(pre and post increment/decrement) • Applies to bidirectional and random access • *p (de-referencing) • Applies to bidirectional and random access • p==p1(test for equality) • Applies to bidirectional and random access

  36. p+=i, p-=i (increment/decrement iterator p by i positions) • Applies to random access only • p[i] (returns a reference to the element offset from p by i positions) • Applies to random access only • p<=p1(returns true if iterator p less than iterator p1 (ie it is before p1 in the container) • Applies to random access only

  37. Example. vector • Enables efficient random access rather like an array but can re-size itself • Supports a random access iterator • All STL algorithms can operate on a vector as they all support random access • A vector has a size (the actual number of elements in the container) and a capacity (the number of elements that can be added before the vector resizes)

  38. #include <vector> int main() { int array[6]={1,2,3,4,5,6}; vector<int> vec(array,array+6); for (int *ptr=array; ptr!=(array+6); ptr++) cout<<*ptr; vector<T>::iterator it; for (it=vec.begin(); it!=vec.end(); it++) cout << *it; // sort the vector sort(vec.begin(),vec.end()); }

  39. The previous program shows the similarity between array access using pointers and container access using an iterator • Also de-referening an iterator (pointer) to access the container (array) element • Also the program shows how a sort() function is called • Iterators passed as arguments • In general the STL is enormously powerful and should always be used in preference to custom written container classes

More Related