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