133
public:
class
Iterator
{
//
Базовый класс внешнего итератора
public:
virtual bool More() = 0;
virtual Type* Next() = 0;
};
};
Iterator* SetBase::ProvideIterator()
{
return
new
InternalIterator(this);
}
void SetBase::AddObject(void* entry)
{
void*
v;
History*
h;
if (At(entry, v)) {
// Уже есть – проверить время
h = (History*)v;
if
(!h->Exists())
//
Необходимо выполнить вставку
h->Insert(Timestamp());
}
else
{
//
Еще нет
h = new History;
h->Insert(Timestamp());
AddEntry(entry,
h);
}
}
void SetBase::RemoveObject(void* entry)
{
void*
v;
History*
h;
if (At(entry, v)) {
// Уже есть – проверить время
h = (History*)v;
if
(h->Exists())
//
Необходимо выполнить удаление
h->Remove(Timestamp());
}
}
bool SetBase::Exists(void* entry, Timestamp ts)
{
void*
v;
return At(entry, v) && ((History*)v)->Exists(ts);
}
bool SetBase::Exists(void* entry)
{
void*
v;
return At(entry, v) && ((History*)v)->Exists();
}
Существуют и другие возможности, которые можно было добавить, но и показанного вполне хватит
для демонстрации рассматриваемой методики.
134
Внутренний итератор
Чтобы реализовать функцию
ProvideIterator()
, мы создаем как нетипизированный внутренний
итератор, ограниченный файлом .cpp и производный от
SetBase::Iterator
, так и внешний — в виде
параметризованной, безопасной по отношению к типам оболочки. Ниже приведен код внутреннего
итератора, объявленного статически (то есть локального по отношению к файлу .cpp). Вся логика
временных пометок спрятана в реализации этого класса.
// В файле set.cpp
class InternalIterator : public SetBase::Iterator {
private:
Dictionary*
dictionary;
Dictionary::Slot*
slot;
//
Текущая позиция
Timestamp
my_time;
//
Время рождения данного итератора
public:
InternalIterator(Dictionary*
d)
: dictionary(d), slot(d->First()), my_time() {}
virtual bool More();
virtual void* Next();
};
bool InternalIterator::More()
{
void*
key;
void*
h;
if (!dictionary->GetCurrent(slot, key, h))
return
false;
//
позиция выходит за текущие границы
do
if
(((History*)h)->Exists(my_time))
return
true;
while (dictionary->GetNext(slot, key, h));
return
false;
}
void* InternalIterator::Next()
{
void*
key;
void*
key1;
void*
h;
//
Предполагается, что клиент сначала вызвал More(),
//
поэтому объект GetNext() не устарел
dictionary->GetCurrent(slot, key, h);
dictionary->GetNext(slot,
key1,
h);
return
key;
}
Параметризованная оболочка, безопасная по отношению к типам
Наконец, в приведенном ниже параметризованном классе все становится безопасным по отношению к
типам и начинает радовать глаз. Внешний итератор представляет собой параметризованную оболочку
для внутреннего итератора, предоставляемого
SetBase
.
template
class Set : private SetBase {
Do'stlaringiz bilan baham: |