The C++ Standard Template Library
The C++ Standard Template Library
Douglas C. Schmidt
What is STL? Generic Programming: Why Use STL? Overview of STL concepts & features e.g., helper class & function templates, containers, iterators, generic algorithms, function objects, adaptors A Complete STL Example References for More Information on STL
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
What is STL?
The Standard Template Library provides a set of well structured generic C++ components that work together in a seamless way. Alexander Stepanov & Meng Lee, The Standard Template Library
Helper class & function templates: operators, pair Container & iterator class templates Generic algorithms that operate over iterators Function objects Adaptors
Enables generic programming in C++ Each generic algorithm can operate over any iterator for which the necessary operations are provided Extensible: can support new algorithms, containers, iterators
Vanderbilt University
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
int main() { std::deque<int> a_deck; a_deck.push_back (3); a_deck.push_front (1); a_deck.insert (a_deck.begin () + 1, 2); a_deck[2] = 0; std::copy (a_deck.begin (), a_deck.end (), std::ostream_iterator<int> (std::cout, " ")); return 0; }
Vanderbilt University
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
10
Vanderbilt University
11
Douglas C. Schmidt
Douglas C. Schmidt
A pair binds a key (known as // Constructor the rst element) with an pair (const T& associated value (known as the : first (t), }; second element)
Vanderbilt University
12
Vanderbilt University
13
Douglas C. Schmidt
Douglas C. Schmidt
An std::map associates a value with each unique key a students id number Its value type is implemented as pair<const Key, Data>
typedef std::map<std::string, int> My_Map; struct print { void operator () (const My_Map::value_type &p) { std::cout << p.second << " " << p.first << std::endl; } }; int main() { My_Map my_map; for (std::string a_word; std::cin >> a_word; ) my_map[a_word]++; std::for_each (my_map.begin(), my_map.end(), print ()); return 0; }
Vanderbilt University
14
Vanderbilt University
15
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
16
Vanderbilt University
17
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
18
Vanderbilt University
19
Douglas C. Schmidt
Douglas C. Schmidt
Iterator categories are hierarchical, with more rened categories adding constraints to more general ones Forward iterators are both input & output iterators, but not all input or output iterators are forward iterators Bidirectional iterators are all forward iterators, but not all forward iterators are bidirectional iterators All random access iterators are bidirectional iterators, but not all bidirectional iterators are random access iterators Native types (i.e., pointers) that meet the requirements can be used as iterators of various kinds
for (int i = 1; i < argc; ++i) projects.push_back (std::string (argv [i])); for (std::vector<std::string>::iterator j = projects.begin (); j != projects.end (); ++j) std::cout << *j << std::endl; return 0; }
Vanderbilt University
20
Vanderbilt University
21
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
22
Vanderbilt University
23
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
24
Vanderbilt University
25
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
26
Vanderbilt University
27
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
28
Douglas C. Schmidt
Douglas C. Schmidt
std::cout << "j < i" : std::cout << "not (j < i)"; << endl; std::cout << "j > i" : std::cout << "not (j > i)"; << endl; j <= i ? std::cout << "i & j equal" : std::cout << "i & j not equal"; std::cout << endl;
Vanderbilt University
30
Vanderbilt University
31
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
32
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
35
Douglas C. Schmidt
Douglas C. Schmidt
int main (int argc, char *argv[]) { std::vector <std::string> projects; for (int i = 1; i < argc; ++i) projects.push_back (std::string (argv [i])); std::vector<std::string>::iterator j = std::find (projects.begin (), projects.end (), std::string ("Lab8")); if (j == projects.end ()) return 1; assert ((*j) == std::string ("Lab8")); return 0; }
Vanderbilt University
36
Vanderbilt University
37
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
38
Vanderbilt University
39
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
40
Vanderbilt University
41
Douglas C. Schmidt
Douglas C. Schmidt
Removes from the range [first, last) the elements with a value equal to value & returns an iterator to the new end of the range, which now includes only the values not equal to value
#include <iostream> #include <algorithm> #include <iterator> int main () { int myints[] = {10, 20, 30, 30, 20, 10, 10, 20}; int *pbegin = myints, *pend = myints + sizeof myints / sizeof *myints; std::cout << "original array contains:"; std::copy (pbegin, pend, std::ostream_iterator<int> (std::cout, " ")); int *nend = std::remove (pbegin, pend, 20); std::cout << "\nrange contains:"; std::copy (pbegin, nend, std::ostream_iterator<int> (std::cout, " ")); std::cout << "\ncomplete array contains:"; std::copy (pbegin, pend, std::ostream_iterator<int> (std::cout, " ")); std::cout << std::endl; return 0; } Vanderbilt University 42
Removes from the range [first, last) the elements for which pred applied to its value is true, & returns an iterator to the new end of the range, which now includes only the values for which pred was false.
#include <iostream> #include <algorithm> struct is_odd { // Could also be a C-style function. bool operator () (int i) { return (i%2)==1; } }; int main () { int myints[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int *pbegin = myints; int *pend = myints + sizeof myints / sizeof *myints; pend = std::remove_if (pbegin, pend, is_odd ()); std::cout << "range contains:"; std::copy (pbegin, pend, std::ostream_iterator<int> (std::cout, " ")); std::cout << std::endl; return 0; } Vanderbilt University 43
Douglas C. Schmidt
Douglas C. Schmidt
class to_lower { public: char operator() (char c) const { return isupper (c) ? tolower(c) : c; } };
int main() { std::vector<float> v (5, 1); // a vector of 5 floats all initialized to 1.0. std::partial_sum (v.begin(), v.end(), v.begin()); std::transform(v.begin(), v.end(), v.begin(), v.begin(), std::multiplies<float>()); std::copy (v.begin (), v.end (), std::ostream_iterator<float> (std::cout, "\n")); std::transform(v.begin(),v.end(), v.begin (), std::bind2nd(std::divides<float>(), 3)); std::copy (v.begin (), v.end (), std::ostream_iterator<float> (std::cout, "\n")); return 0;
Vanderbilt University
44
Vanderbilt University
45
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
46
Douglas C. Schmidt
Douglas C. Schmidt
STL Adaptors
STL adaptors implement the Adapter design pattern i.e., they convert one interface into another interface clients expect Container adaptors include stack, queue, priority queue Iterator adaptors include reverse iterators & back inserter() iterators Function adaptors include negators & binders STL adaptors can be used to narrow interfaces (e.g., a stack adaptor for vector)
int main (int argc, char *argv[]) { std::vector <std::string> projects; for (int i = 0; i < argc; ++i) projects.push_back (std::string (argv [i])); // Sort in descending order: note explicit ctor for greater std::sort (projects.begin (), projects.end (), std::greater<std::string> ()); return 0; }
Vanderbilt University
48
Vanderbilt University
49
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
50
Vanderbilt University
51
Douglas C. Schmidt
The C++ STL #include <queue> // priority_queue #include <string> #include <iostream>
Douglas C. Schmidt
struct Place { unsigned int dist; std::string dest; Place (const std::string dt, size_t ds) : dist(ds), dest(dt) {} bool operator< (const Place &right) const { return dist < right.dist; } }; std::ostream &operator << (std::ostream &os, const Place &p) { return os << p.dest << " " << p.dist; } int main () { std::priority_queue <Place> pque; pque.push (Place ("Poway", 10)); pque.push (Place ("El Cajon", 20)); pque.push (Place ("La Jolla", 3)); for (; !pque.empty (); pque.pop ()) std::cout << pque.top() << std::endl; return 0; }
Vanderbilt University
52
Vanderbilt University
53
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
55
Douglas C. Schmidt
Douglas C. Schmidt
57
Douglas C. Schmidt
The C++ STL #include #include #include #include #include #include #include <vector> <iostream> <algorithm> <iterator> <functional> <cstdlib> <ctime>
Douglas C. Schmidt
int main (int argc, char *argv[]) { std::vector<int> v (10, 2); std::partial_sum (v.begin (), v.end (), v.begin ()); std::random_shuffle (v.begin (), v.end ()); std::copy (v.begin (), v.end (), std::ostream_iterator<int> (std::cout, "\n")); std::cout << "number greater than 10 = " << count_if (v.begin (), v.end (), std::bind2nd (std::greater<int>(), 10)) << std::endl; return 0; }
int main (int argc, char *argv[]) { srand (time(0)); std::vector<int> v, v2 (10, 20); std::generate_n (std::back_inserter (v), 10, rand); std::transform (v.begin (), v.end (), v2.begin (), v.begin (), std::modulus<int>()); std::copy (v.begin (), v.end (), std::ostream_iterator<int> (std::cout, "\n")); std::cout << std::endl; int factor = 2; std::transform (v.begin (), v.end (), v.begin(), std::bind2nd (std::multiplies<int> (), factor)); std::copy (v.begin (), v.end (), std::ostream_iterator<int> (std::cout, "\n")); return 0; } Vanderbilt University 59
Vanderbilt University
58
Douglas C. Schmidt
The C++ STL #include #include #include #include #include <vector> <algorithm> <functional> <iostream> <iterator>
Douglas C. Schmidt
int main() { // Contrasts std::remove_if() & erase(). std::vector<int> v; v.push_back (1); v.push_back (4); v.push_back (2); v.push_back (8); v.push_back (5); v.push_back (7); std::copy (v.begin (), v.end (), std::ostream_iterator<int> (std::cout, " ")); int sum = std::count_if (v.begin (), v.end (), std::bind2nd (std::greater<int>(), 5)); std::cout << "\nThere are " << sum << " number(s) greater than 5" << std::endl; std::vector<int>::iterator new_end = // "remove" all the elements less than 4. std::remove_if (v.begin (), v.end (), std::bind2nd (std::less<int>(), 4)); v.erase (new_end, v.end ()); std::copy (v.begin (), v.end (), std::ostream_iterator<int> (std::cout, " ")); std::cout << "\nElements less than 4 removed" << std::endl; return 0; } Vanderbilt University 61
Douglas C. Schmidt
The C++ STL #include #include #include #include #include <vector> <iostream> <iterator> <algorithm> <functional>
Douglas C. Schmidt
int main() { std::vector<int> v1; v1.push_back (1); v1.push_back (2); v1.push_back (3); v1.push_back (4); std::vector<int> v2; std::remove_copy_if (v1.begin(), v1.end(), std::back_inserter (v2), std::bind2nd (std::greater<int> (), 3)); std::copy (v2.begin(), v2.end (), std::ostream_iterator<int> (std::cout, "\n")); std::vector<int> v3; std::remove_copy_if (v1.begin(), v1.end(), std::back_inserter (v3), std::not1 (std::bind2nd (std::greater<int> (), 3))); std::copy (v3.begin(), v3.end (), std::ostream_iterator<int> (std::cout, "\n")); return 0; } Vanderbilt University 63
Vanderbilt University
62
Douglas C. Schmidt
The C++ STL int main() { std::vector<WrapInt> v (10); for (int i = 0; i <10; i++) v[i] = WrapInt (i+1); std::cout << "Sequence contains: "; std::for_each (v.begin (), v.end (), std::mem_fun_ref (&WrapInt::showval)); std::cout << std::endl;
Douglas C. Schmidt
std::vector<WrapInt>::iterator end_p = // remove the primes std::remove_if (v.begin(), v.end(), std::mem_fun_ref (&WrapInt::is_prime)); std::cout << "Sequence after removing primes: "; for_each (v.begin (), end_p, std::mem_fun_ref (&WrapInt::showval)); std::cout << std::endl; return 0;
Vanderbilt University
65
The C++ STL #include #include #include #include #include <vector> <iostream> <iterator> <algorithm> <functional>
Douglas C. Schmidt
Douglas C. Schmidt
int main () { std::vector<char *> v; v.push_back ("One"); v.push_back ("Two"); v.push_back ("Three"); v.push_back ("Four"); std::cout << "Sequence contains:"; std::copy (v.begin (), v.end (), std::ostream_iterator<char *> (std::cout, " ")); std::cout << std::endl << "Searching for Three.\n"; std::vector<char *>::iterator it = std::find_if (v.begin (), v.end (), std::not1 (std::bind2nd (std::ptr_fun (strcmp), "Three"))); if (it != v.end ()) { std::cout << "Found it! Here is the rest of the story:"; std::copy (it, v.end (), std::ostream_iterator<char *> (std::cout, "\n")); } return 0; } Vanderbilt University 66
Vanderbilt University
67
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
68
Vanderbilt University
69
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
70
Vanderbilt University
71
Douglas C. Schmidt
Douglas C. Schmidt
size_t start_time_; Meeting (const std::string &title, // Meeting start time in HHMM format Day_Of_Week day, size_t start_time, size_t finish_time_; size_t finish_time); // Meeting finish time in HHMM format Meeting (const Meeting & m); }; Meeting (char **argv); Meeting &operator = (const Meeting &m); bool operator < (const Meeting &m) const; bool operator == (const Meeting &m) const; // Helper operator for output std::ostream & operator << (std::ostream &os, const Meeting & m);
Vanderbilt University
72
Vanderbilt University
73
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
74
Vanderbilt University
75
Douglas C. Schmidt
Douglas C. Schmidt
Vanderbilt University
76
Vanderbilt University
77
Douglas C. Schmidt
Douglas C. Schmidt