600.120 Intermediate Programming, Spring 2017* Misha Kazhdan *Much of the code in these examples is not commented because it would otherwise not fit on the slides. This is bad coding practice in general and you should not follow my lead on this.
Outline Iterators
Iterators In our code, we often work with lists of values: vec.h class Vec T* _values; size_t _size; Vec( int size ) : _size(size) _values = new T[_size]; ~Vec( void ) delete[] _values; size_t size( void ) const return _size; T& operator[] ( size_t i ) return _values[i]; const T& operator[] ( size_t i ) const return _values[i]; #include <iostream> #include "vec.h" using namespace std; >>./a.out 0 main.cpp 3 5 >> void Print( const Vec< int >& v ) for( size_t i=0 ; i<v.size() ; i++ ) cout << v[i] << endl; int main( void ) Vec< int > v( 3 ); v[0] = 0, v[1] = 3, v[2] = 5; Print( v ); return 0;
Iterators In our code, we often work with lists of values: list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ) : value(v), next(n) Note: The constructor performs default initialization if the second argument is not provided. (Can only provide default values for the last arguments.) #include <iostream> #include "list.h" using namespace std; >>./a.out 0 main.cpp 3 5 >> void Print( const List< int >& l ) for( const List< int >* i=&l ; i!=null ; i=i->next ) cout << i->value << endl; int main( void ) List< int > l1( 0 ), l2( 3 ), l3( 5 ); l1.next = &l2, l2.next = &l3; Print( l1 ); return 0;
Iterators When working with lists of objects, we don't want to special-case the type-specific ways for running through the elements of the list #include <iostream> #include "vec.h" using namespace std; main.cpp #include <iostream> #include "list.h" using namespace std; main.cpp void Print( const Vec< int >& v ) for( size_t i=0 ; i<v.size() ; i++ ) cout << v[i] << endl; void Print( const List< int >& l ) for( const List< int >* i=&l ; i!=null ; i=i->next ) cout << i->value << endl;
Iterators In our code, we often work with lists of values: We unify the iteration by defining an auxiliary "pointer-like" object / iterator for walking through the list We need to: Get an iterator that "points" to the beginning of the list Get an iterator that "points" just past the end of the list Be able to dereference the iterator Be able to advance the iterator Be able to check if two iterators are equal main.cpp template< typename Container > void Print( const Container& c ) for( PointerLikeObject p=c.begin() ; p!=c.end() ; ++ p ) cout << *p << endl;
Iterators In C++, when we have a container class, we define the iterator as a public nested class called: container.h iterator if we want to be able to modify the values of the reference const_iterator if we do not class Container class iterator
Iterators In C++, when we have a container class, we define the iterator as a public nested class called: container.h The iterator must overload: The reference operator The increment operator The inequality operator class Container class iterator T& operator * ( ); iterator& operator ++ (); bool operator!= ( const iterator& i ) const;
Iterators In C++, when we have a container class, we define the iterator as a public nested class called: container.h The iterator must overload: The reference operator The increment operator The inequality operator The container must define: A begin method An end method class Container class iterator iterator begin( void ); iterator end( void ); const_iterator begin( void ) const; const_iterator end( void ) const;
Iterators Putting these together, we can define generic code: main.cpp template< typename C > void Print( const C& c ) for( typename C::const_iterator i=c.begin() ; p!=c.end() ; ++i ) cout << *i << endl; Note: The keyword typename is needed to let the compiler know that const_iterator is a class / type, not a static member. class Container class iterator container.h iterator begin( void ); iterator end( void ); const_iterator begin( void ) const; const_iterator end( void ) const;
Iterators: Vec vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr )
Iterators: Vec dereference vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr ) const T& operator * ( ) const return *_ptr;
Iterators: Vec pre-increment vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr ) const T& operator * ( ) const return *_ptr; const_iterator& operator ++ () _ptr++ ; return *this;
Iterators: Vec inequality vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr ) const T& operator * ( ) const return *_ptr; const_iterator& operator ++ () _ptr++ ; return *this; bool operator!= ( const const_iterator& i ) const return _ptr!=i._ptr;
Iterators: Vec beginning / ending iterators vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr ) const T& operator * ( ) const return *_ptr; const_iterator& operator ++ () _ptr++ ; return *this; bool operator!= ( const const_iterator& i ) const return _ptr!=i._ptr; const_iterator begin( void ) const return const_iterator( _values ); const_iterator end( void ) const return const_iterator( _values+_size );
Iterators: List list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ); const List< T >* _ptr; const_iterator( const List< T >* ptr ) : _ptr( ptr )
Iterators: List dereference list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ); const List< T >* _ptr; const_iterator( const List< T >* ptr ) : _ptr( ptr ) const T& operator * ( ) const return _ptr->value;
Iterators: List pre-increment list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ); const List< T >* _ptr; const_iterator( const List< T >* ptr ) : _ptr( ptr ) const T& operator * ( ) const return _ptr->value; const_iterator& operator ++ () _ptr=_ptr->next ; return *this;
Iterators: List inequality list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ); const List< T >* _ptr; const_iterator( const List< T >* ptr ) : _ptr( ptr ) const T& operator * ( ) const return _ptr->value; const_iterator& operator ++ () _ptr=_ptr->next ; return *this; bool operator!= ( const const_iterator& i ) const return _ptr!=i._ptr;
Iterators: List beginning / ending iterators list.h class List List< T >* next; T value; List ( T v, List< T >* n=null ); const List< T >* _ptr; const_iterator( const List< T >* ptr ) : _ptr( ptr ) const T& operator * ( ) const return _ptr->value; const_iterator& operator ++ () _ptr=_ptr->next ; return *this; bool operator!= ( const const_iterator& i ) const return _ptr!=i._ptr; const_iterator begin( void ) const return const_iterator( this ); const_iterator end( void ) const return const_iterator( NULL );
Iterators: Vec When the iterator is a pointer, things can be made simpler vec.h class Vec T* _values; size_t _size; Vec( int size ); ~Vec( void ); size_t size( void ) const; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const T* _ptr; const_iterator( const T* ptr ) : _ptr( ptr ) const T& operator * ( ) const return *_ptr; const_iterator& operator ++ () _ptr++ ; return *this; bool operator!= ( const const_iterator& i ) const return _ptr!=i._ptr; const_iterator begin( void ) const return const_iterator( _values ); const_iterator end( void ) const return const_iterator( _values+_size );
Iterators: Vec When the iterator is a pointer, things can be made simpler vec.h class Vec const T* _ptr; T* _values; const_iterator( const T* ptr ) : _ptr( ptr ) size_t _size; const T& operator * ( ) const return *_ptr; const_iterator& operator ++ () _ptr++ ; return *this; Vec( int size ); bool operator!= ( const const_iterator& i ) const ~Vec( void ); size_t size( void ) const; return _ptr!=i._ptr; T& operator[] ( size_t i ); const T& operator[] ( size_t i ) const; const_iterator begin( void ) const return const_iterator( _values ); typedef const T* const_iterator; const_iterator end( void ) const return const_iterator( _values+_size ); const_iterator begin( void ) const return _values; const_iterator end( void ) const return _values+_size;
Piazza Resources section Resources tab Exercise 13-2