Надо мне было сделать полиморфный итератор, т.е. чистый интерфейс для итератора, т.к. типы которые итерируются — неизвестны на стадии компиляции. Интерфейс примерно такой:
class MyBaseIterator
{
virtual ~MyBaseIterator() = 0 {}
virtual void start(bool asForward = true) = 0;
virtual void step(bool asForward = true) = 0;
virtual bool done() const = 0;
virtual mytype getFoo() const = 0;
virtual bool seek(int id) = 0;
};
Содержимое конечного класса стало примерно таким:
class CBlablaIterator :
public MyBaseIterator
{
protected:
const IterationType* m_IterObject; //Класс, объект которого итерируем по базовому интерфейсу.
IterationTypeContainer::const_iterator m_IterObjectIt; //Итератор на контейнер-мембер внутри итерируемого объекта.
//bool m_asForward; //Нежелательный параметр, см. далее.
//...
};
Итерируемый объект примерно такой:
typedef std::blabla ContType; //vector, list, map, etc
class IterationType
{
friend class CBlablaIterator;
protected:
//..
ContType m_IterContainer;
public:
void CreateBlablaIterator(MyBaseIterator*& pIt) const;
//...
};
Прочитав
это, реализация на одном однонаправленном итераторе оказалась несложной:
void CBlablaIterator::start(bool asForward)
{
ASSERT(m_IterObject);
if(m_IterObject)
{
if(asForward)
{
m_IterObjectIt = m_IterObject->m_IterContainer.begin();
}
else
{
m_IterObjectIt = m_IterObject->m_IterContainer.rbegin().base();
}
//m_asForward = asForward;
}
}
void CBlablaIterator::step(bool asForward)
{
ASSERT(m_IterObject);
if(m_IterObject)
{
if(asForward)
{
if(m_IterObjectIt != m_IterObject->m_IterContainer.end())
{
m_IterObjectIt++;
}
}
else
{
ContType::const_reverse_iterator reverseIt = m_IterObjectIt;
if(reverseIt != m_IterObject->m_IterContainer.rend())
{
reverseIt++;
m_IterObjectIt = reverseIt.base();
}
}
//m_asForward = asForward;
}
}
Проблема возникла, когда надо было реализовать функцию done. Примерная реализация должна была быть такая:
void CBlablaIterator::done()
{
ASSERT(m_IterObject);
if(m_IterObject)
{
if(m_asForward) //Требует присутствия нежелательного параметра.
{
if(m_IterObjectIt != m_IterObject->m_IterContainer.end())
{
return false;
}
}
else
{
ContType::const_reverse_iterator reverseIt = m_IterObjectIt;
if(reverseIt != m_IterObject->m_IterContainer.rend())
{
return false;
}
}
}
return true;
}
Можно ли как-нибудь обойтись без этого m_asForward? Почему итераторы для двунаправленных контейнеров — однонаправленные?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]