Iterations of encapsulated nested STL containers

Here's a pretty common STL container encapsulation, which allows the Cfoo user to iterate the container without allowing any changes to the internals.

#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 as follows:

 Cfoo myFoo; for (Cfoo::const_iterator it = myFoo.begin(); it != myFoo.end(); ++it) { it->DoSomething(); } 

Now I want to replace std :: vector with 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 instances of Cbar in the same way as before, setting the const_iterator and the begin () method const and end () const.

I don’t understand how to do this, although I suspect that this involves writing a custom iterator. Any thoughts?

+6
source share
1 answer

None of the standard iterators can iterate more than one container, so your assumption is correct - you will have to write a custom iterator.

This can be done in general terms, if you have an intermediate iterator that returns pairs of (begin, end) iterators to internal containers.

Invalid code to run:

 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 only the beginning, I can return to finish it - or not, depending on this implementation, it already covers the same land.

+4
source

Source: https://habr.com/ru/post/892590/


All Articles