Thiago R. Adams website

Home CodeBlog Articles Downloads Links Books About

Websites

Virtual iterator

How to iterate in any kind of STL container with using the same iterator?

using namespace std;

int main()
{
    vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);

    list<int> lst;
    lst.push_back(3);
    lst.push_back(4);

    for (v_iterator<int> it(vec); it.next() ; )
    {
      cout << *it << endl;
    }

    v_iterator<int> it(vec, true); // true arg means "reverse"
    while(it.next())
    {
        cout << it.get() << endl;
    }

    it.reset();
    while(it.next())
    {
        cout << it.get() << endl;
    }

    it.reset(lst);
    while(it.next())
    {
        cout << *it << endl;
    }

    it.reset();
    if (it.next())
    {
        v_iterator<int> it2(it);
        cout << *it2 << endl;
        v_iterator<int> it3;
        it3 = it2;
        cout << *it3 << endl;
    }
}
Source code for the iterator

template<class T>
struct virtual_iterator
{
    virtual void start() = 0;
    virtual bool end() const = 0;
    virtual void next() = 0;
    virtual const T & get() const = 0;
    virtual virtual_iterator * clone() const = 0;
    virtual ~virtual_iterator() {}
};

template<class T>
class virtual_iterator_imp : public virtual_iterator< typename T::value_type >
{
    const typename T::const_iterator m_begin;
    const typename T::const_iterator m_end;
    typename T::const_iterator m_it;

    void start() { m_it = m_begin;  }

    void next()  { ++m_it; }

    bool end() const { return m_it != m_end; }

    typename const T::value_type & get() const { return *m_it; }

    virtual_iterator_imp * clone() const { return new virtual_iterator_imp(*this); }

    bool operator == (const virtual_iterator_imp &); //not imp
    bool operator != (const virtual_iterator_imp &); //not imp

public:
    virtual_iterator_imp(const T & container) :
      m_begin(container.begin()),
          m_end(container.end()),
          m_it()
      {
      }

      virtual_iterator_imp(const virtual_iterator_imp & it) :
      m_begin(it.m_begin),
          m_end(it.m_end),
          m_it(it.m_it)
      {
      }

      virtual_iterator_imp & operator = (const virtual_iterator_imp & it)
      {
          m_begin = it.m_begin;
          m_end = it.end;
          m_it = it.m_it;
          return *this;
      }
};



template<class T>
class virtual_rev_iterator_imp : public virtual_iterator< typename T::value_type >
{
    const typename T::const_reverse_iterator m_rbegin;
    const typename T::const_reverse_iterator m_rend;
    typename T::const_reverse_iterator m_it;

    void start() { m_it = m_rbegin;  }

    void next()  { ++m_it; }

    bool end() const { return m_it != m_rend; }

    typename const T::value_type & get() const { return *m_it; }

    virtual_rev_iterator_imp * clone() const { return new virtual_rev_iterator_imp(*this); }

    bool operator == (const virtual_rev_iterator_imp &); //not imp
    bool operator != (const virtual_rev_iterator_imp &); //not imp

public:
    virtual_rev_iterator_imp(const T & container) :
      m_rbegin(container.rbegin()),
          m_rend(container.rend()),
          m_it()
      {
      }

      virtual_rev_iterator_imp(const virtual_rev_iterator_imp & it) :
      m_rbegin(it.m_rbegin),
          m_rend(it.m_rend),
          m_it(it.m_it)
      {
      }

      virtual_rev_iterator_imp & operator = (const virtual_rev_iterator_imp & it)
      {
          m_rbegin = it.m_rbegin;
          m_rend = it.rend;
          m_it = it.m_it;
          return *this;
      }
};

template<class T>
class v_iterator
{
    virtual_iterator<T> * m_pIt;
    bool m_first;

public:

    template<class ContainerType>
    v_iterator(const ContainerType & container, bool bReverse = false) :
    m_first(true)
    {
        if (bReverse)
            m_pIt = new virtual_rev_iterator_imp<ContainerType>(container);
        else
            m_pIt = new virtual_iterator_imp<ContainerType>(container);
    }

    v_iterator() : m_first(true), m_pIt(0)
    {
    }

    v_iterator(const v_iterator &it) :
    m_first(it.m_first),
        m_pIt(it.m_pIt->clone())
    {
    }

    void swap(v_iterator &it)
    {
        std::swap(it.m_first, m_first);
        std::swap(it.m_pIt, m_pIt);
    }

    ~v_iterator() { delete m_pIt;  }
    void reset() {  m_first = true;  }

    template<class ContainerType>
    void reset(const ContainerType & container, bool reverse = false)
    {
        v_iterator(container, reverse).swap(*this);
    }

    v_iterator& operator =(const v_iterator & it)
    {
        v_iterator(it).swap(*this);
        return *this;
    }

    bool next()
    {
        if (!m_pIt)
            return false;

        if (m_first)
        {
            m_pIt->start();
            m_first = false;
        }
        else
        {
            m_pIt->next();
        }

        return m_pIt->end();
    }

    const T & get() const
    {
        return m_pIt->get();
    }

    const T & operator *() const
    {
        return get();
    }
};

Want to see more? Go to the CodeBlog section.

About the author: I am Thiago Adams. I work as a professional C++ software engineer. I have created this website to share ideas and source code with other people with similar interests.
I would like to hear from you comments, critics, questions and suggestions about this topic or any other part of this website. Email: thiago.adams at gmail dot com