Iterator of the Week

This is on going series of articles showcasing
different uses for STL style iterators in C++. All source code presented here
is copyright 1998-2002 James M. Curran, but may be used freely. All comment and suggestion are welcome.

This is largely based on last week's (OK, it was actually more like two+ weeks ago) iterator, ViewIter. I'm just going to comment on the bits that are different, so you may want to review that one. (It's
also available here on the newsgroup)

One of the things you'll note about ViewIter if you were to try to templatize it, is that it calls two functions that are specific to the
task of getting a CView* out of a CDocument*, namely
GetFirstViewPosition() and GetNextView(). Every POSITION-based MFC collection has two similar,
but nevertheless unique, functions. To turn ViewIter into a template,
we need a way of getting these function names into the template.

The first thought you might have is to try to pass pointers to these functions in as template parameters (it was the first thought I had).
Even had the result worked (which it didn't), it would have been too messy to be practical.

A better method is to create a class for each collection, which gives
these functions common names. Ideally, that would follow the pattern:

Of course, as we'll have to define each such class manually, there's not much use in that template, but it helps to visualize the interface.
The implementations of each of these functions is just a single functions call.
For example:

Here I'm sticking with it being a forward_iterator. ViewIter was also
declared as a forward_iterator, although it was really closer to being the less flexible input_iterator. I decided to scale it up to be a real
forward_iterator, but I not really sure if those changes are safe. We
may have to revisit this point again.

private:
const in* m_src;
POSITION m_pos;
POSITION m_lastpos;
out m_item;

First thing you should note is that I've added a new data member. Yep,
there was a bug in ViewIter. The POSITION goes to NULL when it reaches the final item. We need it to be NULL when it passes the final item.
Hence, lastpos which holds the previous m_pos value. When it goes to null, we're done.

A more subtle point to note, is the types of the source and item members.
m_src is held as a pointer to the container, and m_item is the actual item that it contains. This is a slight change to the interface of ViewIter
where the container (a CDocuement) was passed to the ctor as a pointer (because you were more likely to have a CDocument* than a CDocument
obj). However, for CLists and CMaps, you're more likely to have an object.
Further, the fact that the objects contained in a CDocument were pointers to CView object is incidental. CLists and CMaps can hold object as well
as pointers, so we'll have to adapt.

We pass the src container in by const reference, but store it as a pointer.

We call the static first() function from our helper class to initialize the m_pos member,

We initialize the m_item to 0. I'm a bit torn about this. Half of me says we should explicitly initialize each member, and Half says, since we
don't know exact what type it is, we should let it just default initialize.

Finally, we only move to the first item, if m_pos is not NULL (ie, there is a first item). (Thanks, Igor)