Если вам нужен виртуальный интерфейс для итерации, что-то вроде этого?
#include <iostream>
#include <iterator>
struct Iterable {
virtual int current() = 0;
virtual void advance() = 0;
protected:
~Iterable() {}
};
struct Iterator : std::iterator<std::input_iterator_tag,int> {
struct Proxy {
int value;
Proxy(const Iterator &it) : value(*it) {}
int operator*() { return value; }
};
Iterable *container;
Iterator(Iterable *a) : container(a) {}
int operator*() const { return container->current(); }
Iterator &operator++() { container->advance(); return *this; }
Proxy operator++(int) { Proxy cp(*this); ++*this; return cp; }
};
struct AbstractStorage : private Iterable {
Iterator iterate() {
return Iterator(this);
}
// presumably other virtual member functions...
virtual ~AbstractStorage() {}
};
struct ConcreteStorage : AbstractStorage {
int i;
ConcreteStorage() : i(0) {}
virtual int current() { return i; }
virtual void advance() { i += 10; }
};
int main() {
ConcreteStorage c;
Iterator x = c.iterate();
for (int i = 0; i < 10; ++i) {
std::cout << *x++ << "\n";
}
}
Это не полное решение - я не реализовал Iterator::operator==
или Iterator::operator->
(последнее необходимо, если содержащийся тип является типом класса).
Я храню состояние в классе ConcreteStorage, что означает, что мы не можем иметь несколько итераторов в одном хранилище одновременно. Поэтому, вероятно, вместо того, чтобы Iterable
являлся базовым классом хранилища, должна быть другая виртуальная функция хранилища для возврата нового Iterable
. Тот факт, что это только входной итератор, означает, что все копии итератора могут указывать на один и тот же Iterable
, поэтому им можно управлять с помощью shared_ptr
(и либо Itertable
должен иметь виртуальный деструктор, либо функцию newIterator должен вернуть shared_ptr
или оба).