This chapter serves mainly to gather and organize information about iterators. Some new concepts are also introduced for completeness.

Similar documents
by Pearson Education, Inc. All Rights Reserved. 2

use static size for this buffer

STL: C++ Standard Library

List, Stack, and Queues

I source_beg, source_end; // defines a range of values in a source container // defines the beginning of a range in a destination container

STL components. STL: C++ Standard Library Standard Template Library (STL) Main Ideas. Components. Encapsulates complex data structures and algorithms

Intermediate Programming, Spring 2017*

CSCI-1200 Data Structures Fall 2017 Lecture 10 Vector Iterators & Linked Lists

A linear structure is an ordered (e.g., sequenced) arrangement of elements.

More Advanced Class Concepts

COEN244: Class & function templates

Fast Introduction to Object Oriented Programming and C++

CS11 Advanced C++ Spring 2018 Lecture 2

III. Classes (Chap. 3)

nptr = new int; // assigns valid address_of_int value to nptr std::cin >> n; // assigns valid int value to n

SFU CMPT Topic: Class Templates

Writing Generic Functions. Lecture 20 Hartmut Kaiser hkaiser/fall_2013/csc1254.html

Type Aliases. Examples: using newtype = existingtype; // C++11 typedef existingtype newtype; // equivalent, still works

Vectors of Pointers to Objects. Vectors of Objects. Vectors of unique ptrs C++11. Arrays of Objects

Standard Library Reference

Templates and Vectors

Program construction in C++ for Scientific Computing

1. The term STL stands for?

CSCI-1200 Data Structures Spring 2018 Lecture 10 Vector Iterators & Linked Lists

7.1 Optional Parameters

Software Engineering Concepts: Invariants Silently Written & Called Functions Simple Class Example

Programming in C++ using STL. Rex Jaeschke

Doubly-Linked Lists

Ch. 12: Operator Overloading

Abstract Data Types (ADTs) 1. Legal Values. Client Code for Rational ADT. ADT Design. CS 247: Software Engineering Principles

CS 247: Software Engineering Principles. ADT Design

CS11 Advanced C++ Fall Lecture 1

Outline. 1 Function calls and parameter passing. 2 Pointers, arrays, and references. 5 Declarations, scope, and lifetimes 6 I/O

Advanced Programming in C++ Container Design I

Introduction. Programming in C++ Pointers and arrays. Pointers in C and C++ Session 5 - Pointers and Arrays Iterators

Stacks and their Applications

Iterator Facade. Table of Contents. Overview. Usage. Iterator Core Access operator[] operator-> Reference

Table of Contents. Overview. Usage. Iterator Core Access. operator[] operator-> Reference

CS

Exercise 6.2 A generic container class

OBJECT ORIENTED PROGRAMMING USING C++

std::cout << "Size of long = " << sizeof(long) << " bytes\n\n"; std::cout << "Size of char = " << sizeof(char) << " bytes\n";

UNIT- 3 Introduction to C++

The following is an excerpt from Scott Meyers new book, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs.

General Advise: Don t reinvent the wheel

A linear structure is an ordered (e.g., sequenced) arrangement of elements.

Review. What is const member data? By what mechanism is const enforced? How do we initialize it? How do we initialize it?

Lab 6. Out: Wednesday 9 March 2005

Lecture 21 Standard Template Library. A simple, but very limited, view of STL is the generality that using template functions provides.

Object-Oriented Programming for Scientific Computing

Chapter 5. The Standard Template Library.

CS197c: Programming in C++

Assignment 1: grid. Due November 20, 11:59 PM Introduction

Absolute C++ Walter Savitch

Question Paper Code : 97044

OBJECT ORIENTED PROGRAMMING USING C++ CSCI Object Oriented Analysis and Design By Manali Torpe

2 nd Week Lecture Notes

Overloaded Operators, Functions, and Students

A brief introduction to C programming for Java programmers

Pointers, Dynamic Data, and Reference Types

Object-Oriented Principles and Practice / C++

CE221 Programming in C++ Part 1 Introduction

Polymorphism. Programming in C++ A problem of reuse. Swapping arguments. Session 4 - Genericity, Containers. Code that works for many types.

Introduction to Programming using C++

Chapter 8. Operator Overloading, Friends, and References. Copyright 2010 Pearson Addison-Wesley. All rights reserved

Object-Oriented Design (OOD) and C++

Instantiation of Template class

ADTs & Classes. An introduction

Overload Resolution. Ansel Sermersheim & Barbara Geller Amsterdam C++ Group March 2019

Programming C++ Lecture 6. Howest, Fall 2013 Instructor: Dr. Jennifer B. Sartor

Value categories. PRvalues. Lvalues

C++ Programming Chapter 7 Pointers

G52CPP C++ Programming Lecture 17

15. Pointers, Algorithms, Iterators and Containers II

Pairing off iterators

Container Notes. Di erent Kinds of Containers. Types Defined by Containers. C++11 Container Notes C++11

Iterators. node UML diagram implementing a double linked list the need for a deep copy. nested classes for iterator function objects

CISC 2200 Data Structure Fall, C++ Review:3/3. 1 From last lecture:

pointers & references

G52CPP C++ Programming Lecture 18. Dr Jason Atkin

Outline. 1 About the course

Overload Resolution. Ansel Sermersheim & Barbara Geller ACCU / C++ June 2018

Data Types and Variables in C language

G52CPP C++ Programming Lecture 18

PIC10B/1 Winter 2014 Exam I Study Guide

C++ Basics. Data Processing Course, I. Hrivnacova, IPN Orsay

AIMS Embedded Systems Programming MT 2017

Today. andyoucanalsoconsultchapters6amd7inthetextbook. cis15-fall2007-parsons-lectvii.1 2

14. Pointers, Algorithms, Iterators and Containers II

COP4530 Data Structures, Algorithms and Generic Programming Recitation 4 Date: September 14/18-, 2008

Operator overloading

The Foundation of C++: The C Subset An Overview of C p. 3 The Origins and History of C p. 4 C Is a Middle-Level Language p. 5 C Is a Structured

static CS106L Spring 2009 Handout #21 May 12, 2009 Introduction

Lesson 13 - Vectors Dynamic Data Storage

Sets and MultiSets. Contents. Steven J. Zeil. July 19, Overview of Sets and Maps 4

Faculty of Information and Communication Technologies

Topics. bool and string types input/output library functions comments memory allocation templates classes

Tokens, Expressions and Control Structures

void setup(){ void loop() { The above setup works, however the function is limited in the fact it can not be reused easily. To make the code more gene

Interview Questions of C++

Transcription:

Iterators Overview We have introduced, used, built, and studied iterators in several contexts, including List<>, TDeque<>, and TVector<>. We have seen that ordinary pointers also can be thought of as iterators for arrays. The importance of iterators for List<> was fairly obvious, from their introduction, since there is no other mechanism to access list elements. The importance of iterators for the other containers was perhaps less clear, until we encountered generic algorithms. Now we know that iterators provide a critical interface between generic algorithms and containers, thus enabling the re usability of code for both container and algorithm implementations. Iterators are perhaps the key concept making generic programming actually work. This chapter serves mainly to gather and organize information about iterators. Some new concepts are also introduced for completeness. Iterators are made so useful by giving them a uniform and predictable public interface with which algorithms may act as clients, while targeting specific containers through implementation details. For this reason, it is useful to classify iterators according to their public interface functionality, and it is also useful to prevent the number of categories from growing unmanageably large. C++ iterators may be classified into six categories according to their public interface functionality, as follows: input iterators output iterators forward iterators bidirectional iterators random access iterators adaptor iterators Of these we have so far only encountered bidirectional and random access iterators. These two categories are by far the most common. We will also introduce and use insert iterators, an example in the category of adaptor iterators, but most of the other categories we will leave for your study in the STL itself, as they pertain less to data structures and algorithms. Terminology Support Consistency of terminology is a critical feature for both containers and iterators. The mechanism used in the fsu template library is the typedef statement, which requires self discipline at the human level. The std template library uses the more reliable mechanism of traits, which are classes with no data and no methods, just typedefs, and from which iterator types inherit. Forward Iterators Forward iterators represent the most basic form of general purpose iterator. It is the only category of iterators guaranteed by the C++ standard to be supported by all of the container classes of the STL. (All of the containers in our class library actually support bidirectional iterators, but the vector container in the STL need not do so.) Forward iterators are those that have (at a minimum) all of the public interface shown in the slide. Note that these include tests for equality and non equality, element access via dereference, forward iteration, and all features associated with proper type. These are exactly the functionalities that enable the most basic kind of loop through a container, such as: Container C; Container::Iterator I; for (I = C.Begin(); I!= C.End(); ++I) cout << *I; These are also the functionalities assumed by all of the basic generic algorithms in tcpp/genalg.h. http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 1/9

Bidirectional Iterators Bidirectional iterators are forward iterators with the addition of the two decrement operators to the public interface. The containers List<>, TDeque<>, and TVector<> support bidirectional iterators, and array pointers can also be considered bidirectional iterators. Therefore all of the basic generic algorithms of tcpp/genalg.h may be applied to these types of container, mix and match. Moreover, the generic algorithms of tcpp/gset.h may also be applied to such containers, provided that the containers meet the other assumptions required by these algorithms. Random Access Iterators Random access iterators are bidirectional iterators with the additional features of random access, which means a bracket operator and "pointer" arithmetic (as shown in the slide). The containers TDeque<> and TVector<>, as well as ordinary arrays, support random access iterators. Therefore the generic algorithms of tcpp/gbsearch.h and tcpp/gheap.h may be applied to these types of containers, provided that the other assumptions of the individual algorithms are met. ConstIterators Every iterator type that is associated with a container type also has a version called ConstIterator. A ConstIterator operates with the same functionality as Iterator, except that a ConstIterator does not allow the container to be mutated, or changed, in any way. This is manifested in code as follows: X::Iterator i; X::ConstIterator ci; t = *i; // OK t = *ci; // OK *i = t; // OK *ci = t; // ERROR: attempted use of ci to mutate container (change value at ci) Note the distinction between ConstIterator and const Iterator. The former is itself mutable (we can, for example, call operator ++) but may not be used to mutate the container into which it points. The latter is itself constant, so it would need to be initialized at the point of declaration and could never be changed. The main use of ConstIterator is inside any block where the associated container is constant. In such a block, it is an error to declare an iterator, but OK to declare a ConstIterator: template < typename T > bool IsIn (const List<T> list, T searchval) // List<T>::Iterator i; // ERROR: const environment List<T>::ConstIterator i; // OK: using ConstIterator for (i = list.begin(); i!= list.end(); ++i) // calls "const" versions of Begin, End if (searchval == *i) return true; return false; Note that this code uses the (Const)Iterator only to read from the container. The support for ConstIterators is built in to the container class. A way to implement ConstIterators is explained in the next slide. http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 2/9

Container Support There is generally a tight coupling between a container and its associated iterator type (via declaration of mutual friendship). Moreover, for the container/iterator system to function appropriately there must be support for both terminology and ititialization iterators built in to the container. Terminology Support is illustrated in this code snippet (part of the definition of the container class X): template < typename T > class X... typedef typename I::Iterator typedef ConstRAIterator<I>... Iterator; ConstIterator; Initialization support is supplied via the Begin/End method pairs:... Iterator Begin(); ConstIterator Begin() const; Iterator End(); ConstIterator End() const;... Note the use of the const modifier to distinguish between the overloads of Begin() and End(). Input Iterators Input iterators are specialized toward the purpose of reading data from a source such as an istream where elements can be read but not written, and once passed they cannot be read again. Input iterators can be associated with istreams using adaptors. Input iterators have a dereference operator that is not fully functional in that it can only be used to read a value, not to write a value. In other words, if I is an input iterator, then v = *I; // OK for input iterators is a legal statement but *I = v; // not OK for input iterators is not. (That is, *I may be an rvalue but not an lvalue: it may appear only on the right side of an assignment.) This restriction might be enforced by returning a constant reference instead of a reference by the dereference operator, as illustrated in the slide. Note that this interface is barely enough to serve as the first iterator type for a generic algorithm such as g_copy() (copied here from tcpp/genalg.h): template <class I, class J> void g_copy (I source_beg, I source_end, J dest_beg) while (source_beg!= source_end) *dest_beg++ = *source_beg++; http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 3/9

Output Iterators Output iterators are specialized toward the purpose of writing data to a source such as an ostream or a container where elements can be written but not read, and once passed they cannot be written again. Output iterators can be associated with ostreams using adaptors. Insert iterators, defined below, are output iterators associated with containers. Output iterators have a dereference operator that is not fully functional in that it can only be used to write a value,but not to read a value. In other words, if I is an output iterator, then v = *I; // not OK for output iterators is a not legal statement but *I = v; // OK for output iterators is. (That is, *I may be an lvalue but not an rvalue: it may appear only on the left side of an assignment.) This restriction is enforced by the semantics of the particular output iterator. A typical case is illustrated in the slide, where the return value of operator *() is a (self)reference rather than a reference to a value. Note that this interface is barely enough to serve as the second iterator type for a generic algorithm such as g_copy(). The Iterator Hierarchy This slide illustrates the various iterator categories and how they relate among themselves. Not that these are NOT inheritance relationships in the usual sense of object oriented programming. They are inheritance relationships in the higher sense of patterns, which are often enforced by maintaining intellectual control of a development project. Pattern inheritance can also be enforced by inheritance of "traits", which are essentially classes with no data or functionality, only terminology defined using public typedef statements. The former approach is taken in this course. The latter approach is taken by the C++ STL. Iterator Adaptors Iterator adaptors are iterator classes obtained as adaptor classes of other classes. Suprisingly, sometimes the adaptee class is not an iterator class. ConstIterator ReverseIterator Insert Iterators Stream iterators are iterators adapted from stream classes and facilitate reading from/writing to streams with generic algorithms. Reverse iterators are adapted from forward iterators and serve to re define forward incrementation to be backward incrementation (i.e., decrementation). While not difficult subjects, we will not cover these topics in detail due to there minimal relevance to data structures and algorithms. ConstIterator Adaptor One way to implement ConstIterators for various containers is to define a single adaptor class and use it to adapt all of the container iterator classes. The idea is to just omit the non const versions of the dereference operator and bracket operator. The adaptor is defined for random access iterators, but can be http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 4/9

used for any other iterator type. // // ConstRAIterator<I> definition // template < class I > class ConstRAIterator public: // terminology support typedef typename I::ValueType ValueType; typedef typename I::PointerType PointerType; typedef typename I::ConstPointerType ConstPointerType; typedef typename I::ReferenceType ReferenceType; typedef typename I::ConstReferenceType ConstReferenceType; typedef typename I::ContainerType ContainerType; typedef typename I::Iterator Iterator; typedef ConstRAIterator<I> ConstIterator; // constructors ConstRAIterator (); ConstRAIterator (const ConstRAIterator& i); // copy constructor ConstRAIterator (const I& i); // type converter bool operator == (const ConstIterator& i2) const; bool operator!= (const ConstIterator& i2) const; ConstReferenceType operator * () const; // return element as R value ConstReferenceType operator [] (size_t index) const; // return element as R value ConstIterator& operator = (const ConstIterator & i); ConstIterator& operator ++ (); // prefix increment ConstIterator operator ++ (int); // postfix ConstIterator& operator (); // prefix decrement ConstIterator operator (int); // postfix // "pointer" arithmetic long operator (const ConstIterator & i2) const; // these are template member operators for pointer arithmetic ConstIterator operator + (N n) const; ConstIterator& operator += (N n); ConstIterator& operator = (N n); protected: I i_; ; // // ConstRAIterator<I> implementations // ConstRAIterator<I>::ConstRAIterator () : i_() http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 5/9

ConstRAIterator<I>::ConstRAIterator (const ConstRAIterator& i) : i_(i.i_) ConstRAIterator<I>::ConstRAIterator (const I& i) : i_(i) bool ConstRAIterator<I>::Valid () const return i_.valid(); bool ConstRAIterator<I>::operator == (const ConstRAIterator& i2) const return i_ == i2.i_; bool ConstRAIterator<I>::operator!= (const ConstRAIterator& i2) const return i_!= i2.i_; typename I::ConstReferenceType ConstRAIterator<I>::operator * () const return *i_; typename I::ConstReferenceType ConstRAIterator<I>::operator [] (size_t index) const return i_[index]; ConstRAIterator<I>& ConstRAIterator<I>::operator = (const ConstRAIterator & i) i_ = i.i_; ConstRAIterator<I>& ConstRAIterator<I>::operator ++ () ++i_; ConstRAIterator<I> ConstRAIterator<I>::operator ++ (int) ConstIterator i(*this); http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 6/9

operator ++(); return i; ConstRAIterator<I>& ConstRAIterator<I>::operator () i_; ConstRAIterator<I> ConstRAIterator<I>::operator (int) ConstIterator i(*this); operator (); return i; long ConstRAIterator<I>::operator (const ConstRAIterator<I> & i2) const return i_ i2.i_; ConstRAIterator<I> ConstRAIterator<I>::operator + (N n) const ConstIterator i = *this; i.i_ += n; return i; ConstRAIterator<I>& ConstRAIterator<I>::operator += (N n) i_ += n; ConstRAIterator<I>& ConstRAIterator<I>::operator = (N n) i_ = n; // useage: template < typename T > bool IsIn (const List<T> & list, T searchval) List<T>::ConstIterator i; for (i = list.begin(); i!= list.end(); ++i) // calls "const" versions of Begin, End if (searchval == *i) return true; return false; http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 7/9

Note that this one adaptor can be used for bidirectional and forward iterators because of the fact: template function code is compiled only when it is called in the program under compilation. Thus the random access features will be ignored when adapting bidirectional iterators and in addition the decrement operations will be ignored when adapting forward iterators. Insert Iterator Adaptors An important example of iterator adaptors, especially for use in the study of containers, is the insert iterator adaptor class. There are three versions, each of which overloads operator =() as an inserter into a container. Consider the following class definition: class PushBackIterator public: explicit PushBackIterator (C& x) : Cptr(&x) PushBackIterator <C>& operator = (const typename C::value_type& t) Cptr > PushBack(t); PushBackIterator<C>& operator * () PushBackIterator<C>& operator ++ () PushBackIterator<C>& operator ++ (int) protected: C* Cptr_; ; This class uses a container C with a PushBack() method to create an iterator that can do only one thing use operator *() as an lvalue to insert items at the back of the container. Note that this is actually accomplished by effectively removing functionality from operator *() and overloading the assignment operator. The operator *() and the increment operators are overloaded to perform no function other than to return a self reference. The following usage declares a list L and a PushBackIterator associated with L: List < char > L; PushBackIterator < List < char > > Litr(L); and the call g_copy(v.begin(), V.End(), Litr); has the effect of inserting all of the elements of the vector V to the back of the list L. The declaration of such a PushBackIterator is somewhat cumbersome, since it must be associated with a specific container as well as declared as to type. After the initial declaration, the following template function provides a useful shortcut to repeating the second line in the declaration above just to reassociate the iterator with a particular container object. It returns a PushBackIterator associated with the container. PushBackIterator<C> BackPusher (C& x) return PushBackIterator <C> (x); http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 8/9

// useage: Litr = BackPusher(L); The declaration and use of PushBackIterator adaptors is illustrated in the programs tests/fga.cpp and tests/fgset.cpp. Similar definitions hold for PushFrontIterator and InsertIterator adaptors, with these prototypes: class PushFrontIterator; PushFrontIterator<C> FrontPusher (C& x); class InsertIterator; InsertIterator<C> Inserter (C& x); All three insert iterator adaptor classes and supporting functions are given in tcpp/cinsert.h. http://www.cs.fsu.edu/~lacher/courses/cop4530/lectures/iterators/script.html#link1 9/9