When defining my custom containers, it is more easy and very general (for me) making them iterable by just adding size()
and []
. This is, having the following member methods:
unsigned int size() const { . . . }
T & operator[] (unsigned int pos) { . . . }
In order to benefit from the STL algorithms, I provide an adaptor from any container class having the above methods to an iterator valid for the STL functions. With it, I can write easily things like
MyContainer<int, 5> mc;
IteratorFromContainer<MyContainer<int,5>, int> iter (&mc);
int i=1; for (auto & e : iter) { e = i++; }
for (auto e=iter.begin(); e!=iter.end(); ++e) { cout << (*e) << endl; }
int sum = std::accumulate(iter.begin(), iter.end(), 0);
int prod = std::accumulate(iter.begin(), iter.end(), 1, [](int a, int b) {return a*b;});
Surprisingly (to me) my adaptor (template) class works (the above sample code) equally well with any of the following (1, 2, or 3):
template<typename Container, typename T>
// 1.
class IteratorFromContainer : public std::iterator<input_iterator_tag, T> {
// 2.
class IteratorFromContainer : public std::iterator<output_iterator_tag, T> {
// 3.
class IteratorFromContainer {
Why?. Should not the adaptor derive from std::iterator
always?
What kind of iterator (what _tag) should I use, considering that the iterator is based in random access (size() and []) and has output and input capabilities: RandomAccess, ContinguousIterator
?
Thanks