Возможно, это не очень хорошая идея, но добавить поддержку цикла for(:)
здесь довольно просто. Я буду минимальным.
Я создам iteroid
, не итератор, которого достаточно для поддержки циклов for(:)
. Для этого требуется поддержка ++
, !=
и унарный *
, и ничего больше.
template<class C>
struct index_iteroid {
decltype(auto) operator*()const {
return (*container)[i];
}
index_iteroid(index_iteroid const&)=default;
index_iteroid& operator=(index_iteroid const&)=default;
friend bool operator==(index_iteroid const& lhs, index_iteroid const& rhs) {
return std::tie(lhs.i, lhs.container)==std::tie(rhs.i, rhs.container);
}
friend bool operator!=(index_iteroid const& lhs, index_iteroid const& rhs) {
return !(lhs==rhs);
}
void operator++()&{
++i;
}
index_iteroid(C* c, std::size_t in):i(in), container(c) {}
private:
std::size_t i = 0;
C* container = nullptr;
};
теперь мы используем это:
class IContainer
{
public:
virtual ~IContainer() = default;
virtual Element& operator[](size_t index) = 0;
virtual const Element& operator[](size_t index) const = 0;
virtual size_t size() const = 0;
index_iteroid<IContainer> begin() { return {this, 0}; }
index_iteroid<IContainer> end() { return {this, size()}; }
index_iteroid<IContainer const> begin() const { return {this, 0}; }
index_iteroid<IContainer const> end() const { return {this, size()}; }
};
и вот оно у вас.
void test( IContainer* cont ) {
if (!cont) return;
for(Element& e : *cont) {
// code
}
}
прошу прощения за любые опечатки.
Теперь полный итератор занимает примерно в 2-3 раза больше кода, чем мой iteroid
, но ничего сложного, в основном просто раздражающий шаблон.
Стандарт не особо вам поможет. Для повышения вы можете составить подсчитывающий итератор с помощью итератора / генератора, вызывающего функцию, и вызвать вызов функции []
. В Boost также есть некоторые утилиты, позволяющие сократить время написания полного итератора, если вы хотите обновить итероид до итератора.