Creating an enumerator based on an ATL collection
Okay, I finally got this working. Here are my results after hours of trying to get this right:


Alternatively it is possible to use a while-loop, which feels somehow more natural, a little bit like a foreach loop:

POSITION pos = m_coll.GetStartPosition();

while (pos != nullptr)
{
    IItem* entry = m_coll.GetNextValue(pos);
    entry-&gt;get_Address(&amp;address);
}


Speaking of foreach, I wrote a small macro that makes it possible to actually write it like a foreach-loop:

#define FOREACH(T, entry, collection) \
    POSITION pos = collection.GetHeadPosition(); \
    T entry; \
    while (pos != nullptr &amp;&amp; (entry = collection.GetNextValue(pos)) != nullptr) 


Now a loop can be written like this:

FOREACH(IItem*, item, m_coll)
{
    item-&gt;FooBar();
}


However this only works for CRBMaps, for CAtlMap you have to change the macro to use GetStartPosition() instead (Hooray consistent design!). For other collections this needs to be changed entirely. Also for initializing the enumerator is easier with the traditional for-based apprach, as shown below.
Turns out that the best way appears to be using a traditional old-fashioned array, because that's the fastest and simplest way to store data inside the enumerator. The initialization then receives a pointer to the first and a pointer to the first element after the last one of the array. The third parameter is used to keep the host of the enumerator (typically the creator/this) alive. If IUnknown is ambigouos here, use this-&gt;GetUnknown();.
The flag was chosen right in this scenario, because the array storing a snapshot of entries that can be iterated is out of control after the enumerator has been created and therefor also needs to released by the enumerator.
That's another plus for an traditional array.


Here's the complete code:

STDMETHODIMP CCollectionOnATL::get_NewEnum(IEnumITEM** enumerator)
{
    // Define the type of the enumerator.
    typedef CComEnum&lt;IEnumITEM, &amp;IID_IEnumITEM, IItem*, _CopyInterface&lt;IItem&gt;&gt; IItemEnumerator;

    // Copy all elements to an array that can be iterated.
    size_t elements = m_coll.GetCount();
    IItem** items = new IItem*[elements];
    POSITION pos = m_coll.GetHeadPosition();

    for (size_t element = 0; element &lt; elements; element++)
    {
        IItem* item = m_coll.GetNextValue(pos);

        // Add a reference of the current item to the enumeration.
        item-&gt;AddRef();
        items[element] = item;
    }

    // Create an enumerator for the array.
    CComObject&lt;IItemEnumerator&gt;* pEnum = new CComObject&lt;IItemEnumerator&gt;();
    HRESULT hr;

    if (FAILED(hr = pEnum-&gt;Init(&amp;items[0], &amp;items[elements], this-&gt;GetUnknown(), ATL::AtlFlagTakeOwnership)))
        return hr;

    return pEnum-&gt;QueryInterface(enumerator);
}