Thursday, 14 March 2013

A class which implements 'for each' in unmanaged C++

This is a way to make just about any class implement a C++ 'for each'.  In this example the existing way of iterating round a list is as follows:

CTypedPtrList<CPtrList,int*> myList;
POSITION pos = myList.GetHeadPosition();
while(pos)
{
    int* p = myList.GetNext(pos);
}

You need to implement a begin() and end() function which return an iterator class.
The iterator class must implement:
    void operator++();
    T operator*() const;
    bool operator!=(const iterator& other)

Once you have done this then the compiler will automatically allow you to write your iterator like this:
for each(int* p in myList)
{
}

Note that if your variable is const you may need to implement a version of everything which is const.

See below for a full implementation example built on CTypedPtrList:

template <class T> class PList : public CTypedPtrList<CPtrList> 
{
public:

    // Support for iterators.
    class iterator
    {
    public:
        iterator( PList<T>* p, POSITION pos ) 
            : m_pList(p), m_pos(pos), m_pointer(NULL) 
        {
            if( m_pList )
            {
                m_pos = m_pList->GetHeadPosition();
                if( m_pos )
                    m_pointer = m_pList->GetNext(m_pos);
            }
        }

        void operator++(int) 
        {
            if( m_pos==NULL ) m_pointer = NULL;
            else    m_pointer = m_pList->GetNext(m_pos);
        };

        void operator++()
        {
            this->operator++(0);
        };

        T* operator*() const { return m_pointer; }

        bool operator!=(const iterator& other) const 
        {
            return m_pointer!=other.m_pointer;
        }
    protected:
        PList<T>* m_pList;
        POSITION  m_pos;
        T*        m_pointer;
    };
    //
    iterator begin() { return iterator(this, GetHeadPosition()); }
    iterator end()   { return iterator(NULL,NULL); }
};

No comments:

Post a Comment