240 likes | 356 Vues
E61 CS 342S: Object-Oriented Software Development Laboratory. Generic Programming with Algorithms, Ranges, and Iterators. Christopher Gill Department of Computer Science and Engineering Washington University, St. Louis cdgill@cse.wustl.edu. Thanks to Matthew Hampton and Christine Julien.
E N D
E61 CS 342S: Object-Oriented Software Development Laboratory Generic Programming with Algorithms, Ranges, and Iterators Christopher Gill Department of Computer Science and Engineering Washington University, St. Louis cdgill@cse.wustl.edu Thanks to Matthew Hampton and Christine Julien
Overview • Generic Algorithms • Ranges • Iterators • Concepts and Models • Refinement
Generic Algorithms • A Generic Algorithm • Is independent of the types to which it applies • E.g., sorting integers (long) or intervals (long, long) • Doesn’t require fixed relationships between categories of types • Need not have a common base class • Implementation in C++ • Relies on templates rather than inheritance • Algorithms implemented as function templates • Iterators and containers implemented as class templates
Example: Linear Search • From Austern: “Generic Programming and the STL” • Sequential (linear) search: find char c in string s char * strchr (char* s, char c) { while (*s != 0 && *s != c) ++s; return *s == c ? s : (char *) 0; } • Problem: not very general • “Range” of iteration is always defined up to ‘\0’ character • Only works for a “zero terminated” string in C/C++
Example: Linear Search, Continued • First generalization (Austern, pp. 11): use a range char * find1 (char* first, char* last, char c){ while (first != last && *first != c) ++first; return first; } • Gives an explicit range (calculate its length – how?) • Assumes first is before last (can check – how?) • Note way caller checks for success changed: why?
Ranges • find1 searches all pointers from first up to but not including last • A half-open range: [first, last) • At what position is ‘\0’ in “hello” ? • How much of “hello” would we print ? • Half-open ranges help avoid off-by-one errors • If last - first is negative, then [first, last) is not a valid range (last is before first) • Otherwise the number of elements in the range [first, last) is given by last – first • If first equals last than there are no elements
Ranges, continued • An empty range [p,p) is valid: p – p == 0 • Iteration • if [first, last) is valid and non-empty, then [first+1, last) is also valid • Dividing into sub-ranges • if [first, last) is valid and mid is reachable from first and last is reachable from mid, then [first, mid) and [mid, last) are also valid • Combining sub-ranges • if [first, mid) and [mid, last) are valid, then [first, last) is valid
Example: Linear Search, Continued • Any linear search implementation must offer a way to: • Indicate the sequence over which search will occur • Represent a position within the sequence • Advance to the next element of the sequence • Detect the end of the sequence • Return a value as an indication of success or failure • Notice we said “offer a way” not “provide an interface” • More on the difference between these later
Linear Search with C++ Templates • Second generalization: use templates to parameterize the function argument types template <class T> T * find2(T * first, T * last, T value){ while (first != last && *first != value) ++first; return first; } • How much did the find1 code need to change? • One last problem • What if we want to apply this to a data structure whose ranges can’t be traversed via simple pointers?
Example: Linear Search, Continued • Third generalization: separate iterator type parameter • The STL linear search algorithm (Austern pp. 13): template <class Iterator, class T> Iterator find (Iterator first, Iterator last, const T & value) { while(first != last && *first != value) ++first; return first; } • Our first generic algorithm • Searches any one-dimensional sequence of elements • Notice we did not throw an exception • “Not found” is a normal result, not an aberration
Concepts and Modeling • A concept defines a set of type requirements • A predicate to classify/categorize types • Tells whether or not a type can be used • E.g., we couldn’t use a linked list iterator in find1 • Any specific type that meets the requirements is a model of that concept • E.g., MyLinkedListIterator vs. char * • Different abstractions (linked list vs. array iterators) • No inheritance-based relationship between them • But both may model iterator concept necessary for find
Concepts and Modeling, Continued • What very basic concept does the last expression in STL find, “return first;” assume? • What “happens” to first when it’s returned from function find? • What other capabilities are required by the Iterator concept for STL find ?
Thinking about Concepts • Consider a concept C and a type T • Three perspectives on concepts are useful • A concept as a list of type requirements • What are all the things T needs to support? • The models relation defines a set of types • What other types besides T can be used? • A concept defines a set of valid programs • What algorithms/programs can be implemented using concept C ? • Or we can simply say: a concept includes a set of valid expressions involving some type T and related (to T) types.
Basic Concepts • Assignable • copy an existing object or assign it a new value • X x(y); and x = y; should produce the same resulting values for x. As should the following:tmp = y; x = temp; • Default Constructible • T(); T t; are valid expressions • Equality Comparable • x == y; x != y; are valid expressions • LessThan Comparable • x < y; x > y; are valid expressions • Regular type: one that is Assignable, Default Constructible and Equality Comparable
Iterators and Concepts • Generalization of pointers • Provide an interface between algorithms and data structures • Algorithm manipulates iterators, not containers • STL iterators model five concepts: • Input Iterator • Output Iterator • Forward Iterator • Bidirectional Iterator • Random Access Iterator
Iterator Concept Hierarchy istream style access ostream style access Stream-like access, single pass Input Iterator Output Iterator Linked-list style access Forward Iterator Memory-like access Bi-linked-list style access Bidirectional Iterator Array/buffer style access Random Access Iterator
Input Iterator • Input Iterators: • Provide an istream-like data access model • STL has an istream iterator adapter • Assumes destructiveread at head of stream only • Cannot modify a stream position without reading • Once read, position is consumed (can’t rewind) • Useful classes of algorithms • Simple (advance, find, count, for_each) • Comparison (equal, mismatch, compare) • support copy and assignment
Output Iterators • Output Iterators: • Provide ostream-like data access model • STL has an ostream iterator adapter • Assumes only can write values to tail of stream • Cannot read from the stream • Once written, can’t modify that position (only next one) • Useful classes of algorithms • Copy (copy, transform, replace_copy, etc.) • fill_n • merge
Forward Iterators • Forward Iterators: • Provide persistent data access model • Can both read and write values • Can be constant or mutable • Can save a position, restart from there • Like a dynamically allocated linked list • Useful classes of algorithms • Advanced search (adjacent_find, search) • Min/max • Filtering (remove, unique, stable_partition)
Bi-directional Iterators • Bi-directional Iterators: • Provide persistent data access model • Support motion in both directions • Can rewind • Like a bi-linked dynamically allocated list • Useful classes of algorithms • Reversal (copy_backwards, reverse, etc.) • Next_permutation, prev_permutation • Partition • Inplace_merge
Random Access Iterators • Random Access Iterators: • Provide persistent data access model • Constant time access to kth element for any k • Like contiguous memory buffer/array • Useful classes of algorithms • Random (random_shuffle, random_sample) • Sorting (sort, stable_sort, partial_sort) • Heap (make_heap, push_heap, pop_heap, etc.)
Iterator Values • STL iterator values can be one of 3 kinds: • dereferenceable(first when it’s != last) • past the end(last) • singular(zero pointer) • Iterators may be compared for equality • Iterators may be copied and assigned p == q &*p == &*q *p == *q
Iterator Traits • Value Types • Different Type • Reference Type • Pointer Type • Iterator tag (category): input, output, forward, bidirectional random access.