I’m working with an awkward C library interface for a database containing a set of objects. The objects have a type and lets say that objects of type A contain a set of B objects and so on. Access to an object is via a handle which are defined as follows:
typedef struct
{
int handle;
} AHandleT;
typedef struct
{
int handle;
} BHandleT;
To iterate over an A object’s B children, the following functions are used:
ReturnT getB(AHandleT /*in*/, BHandleT* /*out*/)
ReturnT getBNext(BHandleT /*in*/, BHandleT* /*out*/)
Likewise for iterating over a set of B objects:
ReturnT getC(BHandleT handle/*in*/, CHandleT* subHandle/*out*/)
ReturnT getCNext(CHandleT handle/*in*/, CHandleT* next/*out*/)
In order to work with this interface from C++ I have made the following iterator and I would appreciate your advice with regard to its implementation. Additionally, do you think this is a good approach? Keep in mind that I’m quite new to C++ and I will be writing my code using TDD.
template<class HandleT>
class HandleIterator
{
public:
typedef ReturnT (*GetNext)(HandleT, HandleT*);
HandleIterator(): m_isLast(true)
{
}
template<class ParentHandleT>
HandleIterator(const ParentHandleT parentHandle, ReturnT (*getFirstChild)(ParentHandleT, HandleT*), GetNext getNext): m_isLast(false), m_getNext(getNext)
{
ReturnT rc = getFirstChild(parentHandle, &m_currentHandle);
if(rc == NotExisting)
{
m_isLast = true;
}
}
void operator++()
{
ReturnT rc = m_getNext(m_currentHandle, &m_currentHandle);
if(rc == NotExisting)
{
m_isLast = true;
}
}
void operator++(int)
{
++(*this);
}
const HandleT& operator*() const
{
return m_currentHandle;
}
const HandleT* operator->() const
{
return &m_currentHandle;
}
friend bool operator==(const HandleIterator& left, const HandleIterator& right)
{
return left.m_isLast == right.m_isLast;
}
friend bool operator!=(const HandleIterator& left, const HandleIterator& right)
{
return !(left == right);
}
protected:
HandleT m_currentHandle;
bool m_isLast;
GetNext m_getNext;
};
Once I have a handle, I can then get the data contained within the object using functions of the following form, from the C interface:
ReturnT getAName(AHandleT)
ReturnT getBName(BHandleT)
ReturnT getBOnlyProprty(BHandleT)
But that’s the next stage.
etc.
Your implementation is quite good, especially for a beginner.
Just a couple of remarks:
getFirstChildinstead of providing the first child directly ?++areT& operator++()andT operator++(int)==should compare more thanm_isLast, otherwise it’s confusing. Cannot you compare the handles too ?Finally, when implementing an iterator, consider inheriting from
std::iterator. It does not have any virtual method but provides thetypedefthat are usually expected in an iterator and will remind you that you need to pick a category:std::forward_iterator_taghere, most probably.