CS253: Software Development with C++

Spring 2023

Iterator Interface

Show Lecture.IteratorInterface as a slide show.

CS253 Iterator Interface

VGA, RJ-45 Ethernet, DisplayPort, USB 2.0 interfaces

Big Picture

deque con = {11, 22, 33, 44, 55};
for (auto value : con)
    cout << value << ' ';
11 22 33 44 55 

Why?

deque con = {11, 22, 33, 44, 55};
for (auto value : con)
    cout << value << ' ';
11 22 33 44 55 
deque con = {11, 22, 33, 44, 55};
for (auto it = con.begin(); it != con.end(); ++it) {
    auto value = *it;
    cout << value << ' ';
}
11 22 33 44 55 

Typical structure

    class Container {
      public:
        using value_type = whatever type this contains;
        class iterator;				  // forward declaration
        iterator begin() {
            return iterator(enough data to indicate start of container);
        }
        iterator end() {
            return iterator(enough data to indicate end of container);
        }
    };

    class Container::iterator {
      public:
        iterator(…);				  // establish a location
        value_type& operator*();		  // get value based on state
        iterator& operator++();			  // go to the next item
        bool operator!=(const iterator &) const;  // compare two iterators
      private:
        declare sufficient data to access elements in the container;
    }

Design

Answers, for a string

Since a string s is essentially a dynamic array of char, the answers are easy:

What data establishes a position?char *pointer
What iterator value indicates .begin()?pointer = &s[0]
What iterator value indicates .end()?pointer = &s[s.size()]
How does the iterator get a value?*pointer
How does the iterator go forward?++pointer

This works, but the iterator doesn’t know much about the string, so it can’t avoid incrementing or decrementing too far.

Different answers, for a string

Instead of a pointer into the string data, let’s point to the string object itself:

What data establishes a position?string *con; size_t index;
What iterator value indicates .begin()?con=&s; index=0;
What iterator value indicates .end()?con=&s; index=s.size();
How does the iterator get a value?(*con)[index]
How does the iterator go forward?++index
How does the iterator get the string size?con->size()

Now, the iterator knows the string size, and can do error checking. The iterator has a pointer to the string object itself, so the iterator has access to all data & methods of the string.

Comparison

Consider the differences between the two string::iterator implementations above.

Which is larger?

The second, which has a pointer and an integer.

Do we care?

Probably not. You generally only have a few iterators.

Which can detect incrementing too far?

Only the second. The first has only a pointer. It doesn’t know where the string ends.

Which can detect indirection on .end()?

Only the second. The first has only a pointer. It doesn’t know where the string ends.

Which can skip over certain data?

Only the second. The first wouldn’t know where to stop.

Answers, for a vector<double> vd

A vector<double> vd has the same requirements as a string.

What data establishes a position?vector<double> *con; size_t index;
What iterator value indicates .begin()?con=&vd; index=0;
What iterator value indicates .end()?con=&vd; index=vd.size();
How does the iterator get a value?(*con)[index]
How does the iterator go forward?++index
How does the iterator get the vector size?con->size()

Answers, for a list

A list is a doubly-linked list of nodes, each of which is a struct containing the data and a pointer to the next struct or nullptr.

What data establishes a position?Node *pointer
What iterator value indicates .begin()?pointer = the first node in the list, or nullptr
What iterator value indicates .end()?pointer = nullptr
How does the iterator get a value?pointer->data
How does the iterator go forward?pointer = pointer->next;

Summary

It’s not magic

class Outer {
  public:
    int data;
    class iterator {
        int get() { return data; }  // 🦡 for which Outer object‽
    };
};
c.cc:5: error: invalid use of non-static data member ‘main()::Outer::data’