Here's a fairly normal encapsulation of an STL container which allows the user of Cfoo to iterate the container without allowing changes to the innards.
#include <vector>
class Cfoo
{
public:
    class Cbar
    {
        /* contents of Cbar */
    };
    typedef std::vector<Cbar> TbarVector;
    typedef TbarVector::const_iterator const_iterator;     
public:
    const_iterator begin() const { return( barVector_.begin() ); }
    const_iterator end() const { return( barVector_.end() ); }
private:
    TbarVector barVector_;
};
So far, so good. We can iterate the container like this:
Cfoo myFoo;
for (Cfoo::const_iterator it = myFoo.begin(); it != myFoo.end(); ++it)
{
   it->DoSomething();
}
Now I want to replace the std::vector with say a nested std::vector:
public:
    typedef std::vector<Cbar> TbarVectorInner;
    typedef std::vector<TbarVectorInner> TbarVectorOuter;
private:
    TbarVectorOuter barContainer_;
But I want to be able to iterate over all the instances of Cbar in the same way as before, exposing a const_iterator, and a begin()const and an end()const method.
I'm not clear how to do that, though I suspect it involves writing a custom iterator. Any thoughts?
None of the standard iterators are able to iterate over more than a single container, so your assumption is correct - you'll have to write a custom iterator.
It is possible to do this in a generic fashion, if you have an intermediate iterator that returns pairs of (begin,end) iterators to the inner containers.
Some untested code to get started:
template<typename T, typename OuterIterator, typename InnerIterator>
class Iterator2d : std::Iterator
{
public:
    Iterator2d(OuterIterator begin, OuterIterator end) : m_begin(begin), m_end(end), m_currentOuter(begin)    {
        if (m_currentOuter != m_end)
             m_currentInner = m_begin->first;
        Normalize();
    }
    Iterator2d & operator++()
    {
        if (m_currentOuter != m_end)
        {
            ++m_currentInner;
            Normalize();
        }
        return *this;
    }
    T & operator*()
    {
        return *m_currentInner;
    }
private:
    void Normalize()
    {
        while (m_currentOuter != m_end && m_currentInner == m_currentOuter->second)
        {
            ++m_currentOuter;
            if (m_currentOuter != m_end)
                m_currentInner = m_currentOuter->first;
        }
    }
    OuterIterator m_begin;
    OuterIterator m_end;
    OuterIterator m_currentOuter;
    InnerIterator m_currentInner;
};
This is just a start, I may come back to finish it - or not, depending on this implementation already covers the same ground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With