Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing member access operator-> for ForwardIterator with on-the-fly computed temporary values

I'm implementing an iterator for an adaptor range which lazily evaluates something on an original range. This means: dereferencing the iterator should dereference the underlying iterator and apply some operation on the result, then returning the result of that operation.

T operator*() const {
    return someOperation(*original_iterator);
}

How can I implement operator-> analogous to this operator*? When looking at other iterator's implementations, they usually return a T*. But I can't return a pointer, since the "pointed to object" is a temporary, computed on-the-fly.

What's the usual guidance in this case? May I simply return a T instead?

Although I personally don't need this operator (I could also use (*i).m instead of i->m and the standard algorithms don't seem to depend on -> either), I'd like my iterator to strictly conform to the ForwardIterator concept which is a specialization of InputIterator which requires the implementation of this operator.

like image 881
leemes Avatar asked Oct 21 '14 20:10

leemes


1 Answers

The simplest way is to just use Boost.Iterators to implement your iterators, which takes care of the tricky code.

But the technique used by Boost.Iterators isn't that complicated. It looks like this:

template <typename T>
class proxy_holder {
  T t;
public:
  proxy_holder(const T& t) : t(t) {}
  T* operator ->() const { return &t; }
};

class the_iterator {
  // ...
  proxy_holder<my_proxy> operator ->() const {
    return proxy_holder<my_proxy>(**this);
  }
};

This relies on the fact that arrow operators get chained, i.e. if one arrow operator returns something that isn't a raw pointer, the arrow operator is called on that thing in turn, until you get to a pointer.

like image 183
Sebastian Redl Avatar answered Sep 28 '22 05:09

Sebastian Redl