user3612643 user3612643 - 26 days ago 8x
C++ Question

Simple stream iterator in C++

Consider a Java-like streaming iterator:

template<class V>
struct Iterator
V& next();
bool hasNext();

template<class V>
struct Iterable
Iterator<V> iterator();

How would you cast this into a std::iterator so that you can use it in find, for-loops, etc.

I think I need to start with an InputIterator, but I am struggling with the following things here:

  • meaningful end()?

  • when are they equal()?

  • what about Distance?


It is quite doable, but a pain.

There are going to be solutions in boost that make this easier. But I'll write it "in the raw" based off C++17 concepts, which can be backported to C++11 if you need them (or extracted from boost or other sources).

You'd be generating an input iterator, because that is what Java-like interface supports.

First I'd write a helper. The helper would hold a optional< Iterator<V> > and an optional<V>.

It would support ++. ++ would advance the iterator and read the value into the optional<V>.

It would support unary *. * would return the value in the optional.

bool is_end() returns true if the optional<Iterator<V>> is empty, or if it !.hasNext().

== returns true if and only if both arguments .is_end(). != would just be ! applied to ==.

This helper isn't yet an iterator, but it has most of the key operations.

Then we use this poly_iterator which type erases anything iterator-like. The operations we wrote above on the helper are sufficient.

Then we write a function that takes a Iterable<V> and produces a range<poly_iterator<T>> of the type erasure class above, using the helper pseudo-iterator above. A range<It> is a class that looks like:

template<class It>
struct range {
  It b; It e;
  It begin() const { return b; }
  It end() const { return e; }

plus maybe other utility helpers.

The type erasure step could be skipped if you chose. Just augment the helper written above to be a full-fledged input iterator. Boost has helpers that make this a touch easier. Have the range-returner return that full-fledged input iterator. I happened to have the poly_iterator<T> lying around in another answer, and if you have a hammer that problem sure looks like a nail.

Note that for the code to be really Java-like, we'd want to actually have (smart) pointers to the objects not copies.