Listing 2: Wrapper to treat an IEnum interface as a forward interator

///////////////////////////////////////////////////////////////
// ENUMITER.H

#include <iterator>
#include <algorithm>
#include <exception>

#include <wtypes.h>
#include <winerror.h>

struct BadResult : std::exception {
   HRESULT result;
   BadResult(HRESULT hr) : result(hr) {}
};

template<class IEnum, class Value>
struct EnumAsIterator 
: std::iterator<std::forward_iterator_tag,Value> {

   // construct - copy - destroy
   EnumAsIterator(IEnum* p=0)
   : pEnum(p),pClone(0),nNext(0) {
      if (pEnum) {
         HRESULT result;
         if (result = pEnum->Clone(&pClone))
            throw BadResult(result);
         pEnum = pClone;
         pEnum->AddRef();
         ++*this;
      }
   }
   EnumAsIterator(const EnumAsIterator& r)
   : pEnum(r.pEnum),pClone(0),nNext(r.nNext),value(r.value) {
      if (pEnum) {
         HRESULT result;
         if (result = pEnum->Clone(&pClone))
            throw BadResult(result);
         pEnum->AddRef();
      }
   }
   EnumAsIterator& operator=(const EnumAsIterator& r) {
      if (*this != r) {
         this->~EnumAsIterator();
         new (this) EnumAsIterator(r);
      }
      return *this;
   }
   ~EnumAsIterator() {
      if (pClone) {
         pClone->Release();
         pEnum->Release();
      }
   }

   // comparison
   bool operator==(const EnumAsIterator& r) const {
      return pEnum == r.pEnum && nNext == r.nNext;
   }
   bool operator!=(const EnumAsIterator& r) const {
      return !(*this == r);
   }

   // dereference
   Value operator*() const {
      return value;
   }

   // pre-increment
   EnumAsIterator& operator++() {
      if (pClone) {
         HRESULT result;
         unsigned long n;
         if (result = pClone->Next(1,&value,&n)) {
            if (result == S_FALSE) {
               pClone->Release(), pClone = 0;
               pEnum->Release(), pEnum = 0;
               nNext = 0;
            } else
               throw BadResult(result);
         } else
            nNext++;
      }
      return *this;
   }

   // post-increment
   EnumAsIterator operator++(int) {
      EnumAsIterator tmp(*this);
      ++*this;
      return tmp;
   }

private:
   IEnum *pEnum, *pClone;
   unsigned long nNext;
   Value value;
};
//End of File