CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things...

22
CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things Point to the start of a range of elements (in a container) Give access the current element to which it points An iterator may be able to do 2 other important things Move to point to the next element in a range Be tested for having run through the entire range Intent (according to Gamma et al., “Design Patterns”) Provide a way to access elements of a container sequentially without exposing its underlying representation Iterators help provide interface polymorphism Same interface, but different iterator implementations Due to underlying containers’ different behaviors We’ll consider iterator interface methods above with istream, ostream, array, linked list, bi-linked list

Transcript of CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things...

Page 1: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

What is an Iterator?• An iterator must be able to do 2 main things

– Point to the start of a range of elements (in a container)– Give access the current element to which it points

• An iterator may be able to do 2 other important things – Move to point to the next element in a range– Be tested for having run through the entire range

• Intent (according to Gamma et al., “Design Patterns”)– Provide a way to access elements of a container

sequentially without exposing its underlying representation• Iterators help provide interface polymorphism

– Same interface, but different iterator implementations– Due to underlying containers’ different behaviors

• We’ll consider iterator interface methods above with– istream, ostream, array, linked list, bi-linked list

Page 2: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

STL Iterator Syntax and Semantics

• Pointers and integers are both Gamma et al. iteratorsfor (int * p = &A[0]; p – A < MAX; ++p) {

cout << *p << endl;

}

• Pointers (but not integers) are also STL iterators– Relies on associated types tricks we’ll cover later – Use traits based on typedef/struct/specialization

• The compiler can only check the syntax• Iterator definition must provide good semantics

– Including memory, aliasing, time complexity– Is it ok to implement p += n via a for loop? Why or why

not?

Page 3: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Overview of STL Iterators• STL iterators generalize different uses of pointers

• Interface between algorithms and data structures– Algorithm manipulates iterators, not containers

• STL iterator “value” can be in one of 3 kinds of states:– Dereferenceable (points to a valid location in a range)– Past the end (points just past last valid location in a range)– Singular (points to nothing, like a zero pointer)

• STL iterators may be compared for equality• STL iterators may be copied and assigned • Why are STL iterators designed this way?

Page 4: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Linear Search Example (Based on Austern)char* strchr(char* s, char c) { while (*s != ‘\0’ && *s != c) { ++s; } return s;}

• Not a very general solution – Only handles char (not wchar_t, uchar, etc.)– “Range” is up to but not including the ‘\0’

• Only applies to “zero terminated” strings

• First generalization: use a proper range– Provide an integer range length (how far to count)– Provide a first and last pointer into the array

char* find(char* start, char * end, char c) { while (start != end && *start != c) { ++start; } return start;}

Page 5: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

A Closer Look at Rangeschar* find(char* start, char * end, char c) { while (start != end && *start != c) { ++start; } return start;}

searches all positions in the string (from start up to but not including end) for a position with value c– A closed/open range: [start, end)

• A few questions about ranges to consider– At what position is ‘\0’ in “hello” ?– What is the last element in [0,1) ?

• Closed/open ranges help avoid off-by-one errors– The number of elements in the range [start, end) is end - start

Page 6: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Some Definitions Related to Ranges• A valid range can be traversed safely with an iterator• An empty range [p,p) is valid• If [first, last) is valid and non-empty, then [first+1, last) is also valid– Proof: iterative induction on the range

• If[first, last) is valid – and position mid is reachable from first – and last is reachable from mid– then [first, mid) and [mid, last) are also valid

• If [first, mid) and [mid, last) are valid, then [first, last) is valid– Proof: divide and conquer induction on range

Page 7: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Back to the Linear Search Example• Second generalization (we looked at this code before)template <typename Iterator, typename T>Iterator find2 (Iterator first, Iterator last,

const T & value) { while (first != last && *first != value) { ++first; } return first;}

• With both the iterator and value types being template type parameters, the function becomes very generic – Searches any one-dimensional sequence of elements– But, this raises some important issues about the iterator type

(especially about what other types are associated with it)

Page 8: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

An Important Technique: Traits• If we want to use iterators in templates, then we

need to provide additional info about them– Some information is fairly basic

• Type for expressing distance between iterators• Type obtained when an iterator is dereferenced

– Some information is more subtle and advanced• Whether or not an iterator can move backward, or be

moved an arbitrary distance in constant time

• Why do we need to provide this information?– For basic info, to write code that compiles– For advanced info, to influence compiler’s matching

• To do this across diverse types, we need traits

Page 9: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Motivating Traits: Iterator’s Value Type• Why are traits needed? • See example to the left

– Illustrates problem of writing a generic swap function template

• First approach– Work around the

problem– Let compiler resolve the

value type– Define a forwarding

function– Defer implementation to

an internal function– Can we improve this?

// Austern, pp. 34: can’t write

// template <typename I>

// void swap (I i1, I i2){

// T tmp = *i1;

// *i1 = *i2;

// *i2 = tmp;

// }

template <typename I, typename T>

void swap_impl (I i1, I i2, T t){

T tmp = *i1;

*i1 = *i2;

*i2 = tmp;

}

template < typename I>

void swap (I i1, I i2)

{

swap_impl (i1, i2, *i2);

}

value type

Page 10: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Iterator’s Value Type (continued)

• Second approach– Declare the value

type within a class– Algorithms can then

rely on that type in their concepts

– A step in the right direction, anyway

– What’s the limitation?

// Based on Austern, pp. 34

template <typename T>

class MyIterator {

public:

typedef T value_type;

// ...

private:

T * current_;

};

template <typename I>

void swap (I i1, I i2)

{

I::value_type temp;

// ...

}

Page 11: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Iterator Traits

• Third approach: a partial solution– Type indirection – Via an iterator

traits class– Why do this?– Have we made

progress?

// Based on Austern, pp. 35

template <typename I>

struct iterator_traits {

typedef typename I::value_type value_type;

};

template <typename I>

void swap (I i1, I i2)

{

iterator_traits<I>::value_type temp;

// ...

}

Page 12: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Iterator Traits (continued)

• Fourth approach: a complete solution– Different versions

of iterator_traits– Uses template

specialization– C++ compiler will

select the most specific match

// Based on Austern, pp. 35

template <typename I>

struct iterator_traits {

typedef typename I::value_type

value_type;

};

template <typename T>

struct iterator_traits<T*> {

typedef T value_type;

};

template <typename T>

struct iterator_traits<const T*> {

typedef T value_type; // a subtlety

};

Why do we need this one, too?

Page 13: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

More About Iterators Associated Types• Difference Type

– Type for “distance” between two iterators i1 and i2

– E.g., ptrdiff_t

• Reference, Value Types– For T *p, value type is T, *p

normally returns T &– For const T *p, value type is const

T, *p gives const T &

• Iterator Concept Category– Most refined concept it models– More about how this is used, when

we cover STL algorithms in detailhow far? units?

how far? units?

Page 14: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Iterator Concept Hierarchy

Input Iterator Output Iterator

Forward Iterator

Bidirectional Iterator

Random Access Iterator

•value persists after read/write•values have locations•can express distance between two iterators

•read or write a value (one-shot)

Linked-list style access (slist)

Bi-linked-list style access

(list)Array/buffer style access

(vector, deque)

“destructive” read at head of stream

(istream)

“transient” write to stream (ostream)

Page 15: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Input/Output Iterator Concepts & Models

• Important Input Iterator Concept Expressions*i (read value at the head of the stream)i->m (access member through iterator)++i, i++ (move the iterator to next element in stream)

• Some Models of the Input Iterator Conceptistream_iterator, most other STL iterators

• Important Output Iterator Concept ExpressionsX y(x), X y=x, y = x (copy construct / assign iterators)*x = t, (write value t into the stream) x++, ++x (move the iterator to next element in stream)

• Some Models of Output Iterator Conceptfront_insert_iteratorback_insert_iteratorostream_iterator

Page 16: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Forward/Bidirectional Iterator Concepts & Models• Important Forward Iterator Concept Expressions

– Can pass same forward iterator in multiple arguments

X x, X(),(default construction)

++i, i++ (move from location to location)

*i (non-destructive access to container element)

• Some Models of the Forward Iterator Conceptslist<double>::const_iterator

hash_set<string>::iterator

• Bidireational Iterator Concept also requires--i, i-- (move from location back to earlier location)

• Some Models of the Bidirectional Iterator Conceptlist<int>::iterator, set<string>::iterator

Page 17: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Random Access Iterator Concepts & Models• Important Random Access Iterator Concept

Expressionsi+=n, i-=n (moving iterator given distance in constant time)i+n, n+i, i-n, n-i, i-j, i<j (iterator arithmetic)i[n], i[n]=t (indexing a container using an iterator)– Thought Question: we can express the distance between

two Forward Iterators, so why don’t those iterators have i-j or i<j ?

• Some Models of the Random Access Iterator Conceptvector<int>::iteratordeque<int>::iteratorchar *

• Compiler must be able to determine to which category an iterator belongs– Allows it to match an iterator with

Page 18: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Advice for Designing Your Own Iterators

• Use the iterator concept requirements as a checklist– Also good advice for writing containers and functors

• Make you support both constant and mutable objects• Define associated types appropriately

– More on this in the lecture on generic programming

• Provide as wide an iterator interface as possible without loss of efficiency

• Obey the aliasing rule we talked about with pointers– Two iterators equal if and only if they point to same variable

i == j &(*i) == &(*j)

*i == *j

Page 19: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Advice for Using Iterators• Write a concept expression checklist for iterator

developers to use in designing their iterators

• Watch out for empty ranges

• Require as narrow an iterator interface as possible without loss of efficiency– Avoid over-constraining unnecessarily

– E.g., requiring just == and < vs. also > and !=

• Use selective dispatching techniques to provide both efficiency and generality

Page 20: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

Example of Using Iterators in the STL• From Austern, pp. 355• Copies values from an istream into a vector• What exactly is going on here?

int main () { vector<int> V; copy (istream_iterator<int> (cin), istream_iterator<int> (), back_inserter (V)); }

• (Thanks to Morgan Deters for this example)

Page 21: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

How the Iterator Works in this Example

• From the g++ 2.95.2 STL source code :

template <class _Tp, class _Dist = ptrdiff_t> class istream_iterator { ... public: istream_iterator() : _M_stream(&cin), _M_end_marker(false) {}

istream_iterator(istream& __s) : _M_stream(&__s) { _M_read(); } ... };

Page 22: CSE 332: C++ STL iterators What is an Iterator? An iterator must be able to do 2 main things –Point to the start of a range of elements (in a container)

CSE 332: C++ STL iterators

For Next Time

• Topic: C++ STL Algorithms

• Assigned Reading– pages 930-933

pages 1102-1128