Mars
Mars

Reputation: 4995

Writing a bidirectional iterator for a class

I have a class that holds strings. Basically the class is built on an array of strings:

class stringlist {
public:
    typedef std::string str;
    void push(str);
    void pop();
    void print();
    void resize(size_t);
    size_t capacity();
    size_t size();
    stringlist() : N(15) {}
    stringlist(size_t sz) : N(sz) {}
    ~stringlist() { delete [] container; }
}
private:
    size_t N;
    str* container = new str[N];
};

The next part of the exercise asks readers to

Write a bidirectional iterator for your class

At this point in the book, there is no talk of overloaded operators etc.

If I have something like str* iterator(*str), how would I manage incrementation, decrementation, etc. I am assuming I can write a separate function for these methods but that seems like it would defeat the purpose of writing a iterator data member in the first place. Would the iterator be a separate class?

Also, would it be possible to have the increment decrement functions inside the iterator so that I can dot into the iterator to use these functions?

Upvotes: 5

Views: 3461

Answers (2)

Ben Voigt
Ben Voigt

Reputation: 283773

A pointer is a valid bidirectional iterator. (It is also random-access)

So you can add iterator support to your class with

typedef str* iterator;
typedef const str* const_iterator;
iterator begin() { return container; }
const_iterator begin() const { return container; }
iterator end() { return begin() + size(); }
const_iterator end() const { return begin() + size(); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }

However, you can't use pointers to implement reverse iteration (which uses ++ to go backwards, and -- to go forwards). But the Standard library provides a nice adaptor (in #include <iterator>):

typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crend() const { return rend(); }

Upvotes: 7

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 71009

An iterator is usually implemented as a nested class of the class you iterate. You overload the increment and decrement operators of the nested class. It may make sense now why you write vector<int>::iterator it - iterator is in fact a class nested within vector<int>.

Upvotes: 0

Related Questions