STL – Standard Template Library Guaranteed to be available on all compilers implement the Standard Template library All components are templates, can be used for arbitrary element types.
STL Entities Entities: Container classes Sequence containers Associative ordered containers Iterators Generic algorithms Function objects (functors) Other (not covered here) Allocators Adaptors
Old Structure Queue Stack algorithm List algorithm hash algorithm
New Structure with STL Algorithm Iterator Container Queue List Stack hash Container Algorithm Iterator The iterator is a bridge between Container and Algorithm
Concepts A concept is a set of abstractions Defined by a set of requirements Example: a container concept {vector<T>, list<T>, set<K>, map<K,T>, … } generic algorithms : algorithms that work correctly and efficiently for every abstraction in a concept Definition: Container refines Basic-container; uses Input-iterator; introduces begin(containers) -> iterators, end(containers) -> iterators, size(containers) -> naturals, empty(containers) -> bool; requires (for c: containers) size(c) = size(range(c, begin(c), end(c))), empty(c) = (size(c) = 0), valid(range(c, begin(c), end(c))).
Container A template, parameterized on element type Represents a group of homogeneous objects Two main types: Sequence containers : vector, deque, list Associative containers: set, multiset, map, Multimap All containers support: bool empty() const; iterator begin() const; iterator end() const; int size() const; Containers are characterized by complexity metrics # of operations for insertion, deletion # of operations for lookup
Iterator Points to one node in a list Advances to next node Compares with other iterators Special value denotes “one past end” Make heavily use of operator overloading. Iterator hierarchy
Iterator Example #include <list> // list class library using namespace std; void squareList(list<int>& nums) { list<int>::iterator it; for(it=nums.begin(); it != nums.end(); it++) *it = *it * *it; // Modify each element. }
Sequence Containers vector<T> deque<T> list<T>: Random access, variable size, constant insertion time. Description: http://www.sgi.com/tech/stl/Vector.html deque<T> Random access, variable size Description: http://www.sgi.com/tech/stl/Deque.html list<T>: Bidirectional access, access time O(n), constant insertion time Description: http://www.sgi.com/tech/stl/List.html
Simple Example - list #include <iostream> #include <list> using namespace std; int main(){ list<int> myContainer; list<int>::iterator it; myContainer.push_front(10); myContainer.push_front(20); myContainer.push_back(30); myContainer.push_back(40); for(it=myContainer.begin(); it!=myContainer.end(); it++) cout << *it << endl; myContainer.remove(30); // requires operator== myContainer.find(20); return 0; {
Associative containers Containers based on keys set<key> keys and data are the same, unique keys Description: http://www.sgi.com/tech/stl/set.html multiset<key> keys and data are the same, non-unique keys Description: http://www.sgi.com/tech/stl/multiset.html map<key,T> keys and data are paired, unique keys Description: http://www.sgi.com/tech/stl/Map.html multimap<key,T>: keys and data are pared, non-unique keys Description: http://www.sgi.com/tech/stl/Multimap.html
Example - Map We will define a map of class Person class Person { string m_sName; int m_iAge; public: typedef unsigned key; Person (const string sName, const int iAge): m_sName (sName), m_iAge (iAge) {}; Person () : m_iAge (0) {}; Person (const Person & p): m_sName (p.m_sName), m_iAge (p.m_iAge) {}; Person & operator= (const Person & rhs) {…} GetName () const { return m_sName; }; int GetAge () const { return m_iAge; }; };
Map class People } public: map<Person::key, Person> m_mapPerson; typedef pair<Person::key,Person> PersonPair; friend ostream& operator<<(ostream & s, const People & o){ map<Person::key,Person>::const_iterator it; for(it=o.m_mapPerson.begin();it!=o.m_mapPerson.end(); it++) s << (*it).first << ":" << (*it).second << endl; return s; void insert(Person::key k, Person p){ m_mapPerson[k] = p; };
functors Motivation: Sometimes it is useful to pass functions as parameters Usually results in messy/confusing code Functions can’t hold a meaningful state STL’s solution: function objects (functors) bool lessAbsoluteValue(float a, float b) { return abs(a) < abs(b); } bool (*mycomparison)(float, float); mycomparison = &lessAbsoluteValue; void sort(bool(*cmpfunc)(float, float), std::vector<float>);
functors Classes that implements the function call operator (operator()) Use example: sort(x.begin(), x.end(), lessAbsoluteValue()); class lessAbsoluteValue { public: bool operator()(float a, float b) const { return abs(a) < abs(b); } };
Applying functors to a range struct add { add( int n) : m_n( n) {} void operator()( int & value) { value += m_n; } private: int m_n; }; int main() { int a[] = { 335, 33, 98, 39, 54, 24, 3 }; int nElements = sizeof(a) / sizeof(a[ 0]); std::for_each( a, a + nElements, add( 10)); }
functor adaptors wrapper functors that call member functions mem_fun: works on member functions through a pointer mem_fun_ref: works on member functions through an object or a reference ptr_fun: works on global functions through a function pointer vector<SceneNode*> nodes; … sort(nodes.begin(), nodes.end(), mem_fun(&SceneNode::renderFirst));
Algorithms STL defines many different algorithms Templated function of common operations on containers Four categories of algorithms: Non-mutating algorithms Mutating algorithms Sorting algorithms Generalized numerical algorithms
Non-mutating algorithms find – looks for a specific item in a sequence for_each – applies a functor to a range of elements in a sequence list<string> players; … if (find(players.begin(), players.end(), wantedName) != players.end()) { …} template<class T> struct print { print(ostream& out) : os(out), count(0) {} void operator() (T x) { os << x << ' '; ++count; } ostream& os; int count; }; … int A[] = {1, 4, 2, 8, 5, 7}; const int N = sizeof(A) / sizeof(int); print<int> P = for_each(A, A + N, print<int>(cout));
Mutating Algorithms copy - Copies all elements in a specified range to another range reverse(first, last) – Reverse the elements in the sequence rotate(first, middle, last) – Shifts elements until middle element is at the first position random_shuffle - Shuffles all elements in the range // Copy the first 10 scores to the highscore table list<int> highcores; copy(scores.begin(), scores.begin()+10, highscores.begin());
Sorting algorithms sort Sorts all the elements in a range (based on quicksort) Uses operator< or a functor passed as an argument class Player { public: bool operator<(const Player& p) { return this->score_ < p.score_; } … vector<Player> players; sort(players.begin(), players.end());
Generalized numerical algorithms accumulate(first, last, init) Sums of all elements in a range, starting with initial value partial_sum(first, last, output) Sequence of numbers created by adding all the elements up to the nth element for each of the output elements adjacent_difference(first, last, output) Sequence of differences between adjacent pairs inner_product Calculates dot product for two different ranges
Algorithm+Container+Functor #include <cstring> #include <algorithm> #include <iostream> using namespace std; class CStringCompare { public: bool operator()(const char* s1, const char* s2) { return strcmp(s1, s2) < 0; } }; int main() { vector<string> cartoons; cartoons. push_back(“Mickey”); cartoons. push_back(“Minnie”); cartoons. push_back(“Goofy”); sort(cartoons.begin(), cartoons.end(), StringCompare()); for (int i = 0; i < numberOfArgs; ++i) cout << args[i] << endl; return 0; } Output: Goofey Mickey Minnie