template<class I, class T>
class elm::PreIter< I, T >
This help class provides the definition of iterator operators (), !, ++ (prefix), ++ (postfix), == and !=. These operations are derived from 3 functions that must be declared in class I:
- bool ended() – test if the end of iteration is reached,
- void next() – move to the next item,
- bool equals(const Iter& i) – test equlity of iterators.
By itself, this class is not enough to declare the full set of operators of an iterator. It has to be used in conjunction with ConstPreIter and MutPreIter (or both) that will provide operator * and ->.
Example below shows an example of complete constant and mutable iterators:
template <class T>
class MyArray {
public:
class BaseIter: public PreIter<Iter, T> {
public:
inline BaseIter(
const MyArray&
array,
int idx = 0): a(
array), i(idx) { }
inline bool ended() const { return i >= 10; }
inline void next() const { i++; }
inline bool equals(
const BaseIter& it)
const {
return i == it.i; }
private:
const MyArray<T>& a;
int i;
};
class Iter: public BaseIter, public ConstPreIter<Iter, T> {
public:
using BaseIter::BaseIter;
inline const T& item() const { return BaseIter::a.t[BaseIter::i];
};
inline Iter begin() const { return Iter(*this); }
inline Iter end() const { return Iter(*this, 10); }
class MutIter: public BaseIter, public MutPreIter<Iter, T> {
public:
inline MutIter(MyArray& a, int i = 0): BaseIter(a, i) { }
inline T& item() { return const_cast<MyArray&>(BaseIter::a).t[BaseIter::i]; }
};
inline MutIter begin() { return MutIter(*this); }
inline MutIter end() { return MutIter(*this, 10); }
private:
T t[10];
};
This code defines first a base iterator, BaseIter, that gather all functions that are common to the constant and to the mutable iterator. Then the constant iterator, Iter, can be declared: it uses the same construction as BaseIter but the access to protected fields requires to prefix them with the BaseIter class name: it is a bit ugly but required by the multiple inheritance caused by the use of ConstPreIter.
MutIter is a bit more complex: it inherits from BaseIter re-using the functions defined in BaseIter but also ensuring that Iter and MutIter can be compared.The constructor can not be inherited to ensure that the MyArray parameter is mutable/non-constant.This is important to ensure that the const_cast<>() of the item() is valid. This cast is required in order to expose references to the MyArray items but it is only performed if the constructor has obtained a mutable MyArray.
- Parameters
-
I | Defined iterator. |
T | Type of iterated items. |