Index
C++ iterators are frequently copied and moved around, and can benefit from a reference-counted approach, where only a reference count gets updated, instead of having to copy a large object here and there.
#include <x/refiterator.H> #include <x/ref.H> #include <x/ptr.H> #include <x/obj.H> class customiteratorObj : virtual public x::obj { // ... }; typedef x::refiterator<customiteratorObj> customiterator; auto iter=customiterator::create( /* arguments... */ );
x::refiterator
defines a subclass of x::ref
that implements iterator operator facades which invoke the corresponding
methods from the referenced object. The template, like
x:ref, takes an optional second parameter that
specifies a custom
base class.
x::ptriterator,
x::const_refiterator, and
x::const_ptriterator round out the
rest of the customary naming convention for
references and pointers to a reference-counted object.
The remainder of this chapter refers to
x:refiterator. This description
equally applies to
x::ptriterator and the others, subject to
the inherent differenced between the underlying x::ref and x::ptr
semantics.
At this time, the reference-counted iterator template implements supports only input and output iterators.
auto iter=x::make_refiterator(x::ref<dummyOutputIterObj>::create());
The make_refiterator() convenience function takes
a x::ref parameter, and constructs an
x::refiterator from it.
class dummyOutputIterObj : virtual public x::obj { public: typedef std::iterator<std::output_iterator_tag, void, void, void, void> iterator_traits; std::string buffer; public: dummyOutputIterObj() {} ~dummyOutputIterObj() {} void operator++() {} x::ref<dummyOutputIterObj> before_postoper() { return x::ref<dummyOutputIterObj>(this); } dummyOutputIterObj &operator*() { return *this; } void operator=(char c) { buffer.push_back(c); } dummyOutputIterObj *operator->() { return this; } }; // ... auto iter=x::refiterator<dummyOutputIterObj>::create(); std::string s="foobar"; iter=std::copy(s.begin(), s.end(), iter); *iter++='r';
Like with x::refs and x::ptrs, create() constructs
a reference or a pointer to a new reference-counted object.
x::refiterator implements the
*(), ++(), and
->() operators that are required from an
iterator implementation. They get implemented by invoking the following
methods and members of the referenced object:
typedef std::iterator<...> iterator_traits
The object must declare iterator_traits to
describe what kind of an iterator it implements.
x::refiterator inherits from it.
* and ->
x::refiterator's
* and
-> methods invoke
the corresponding method from the object, and return whatever the
invoked method returns. The * operator is
required, and -> is optional.
As usual, it's expected that an output iterator's
*() returns something that implements
=() that adds a new element to the
output sequence. The usual approach is to return a native
reference to the same object, and have the class implement
the = operator.
Unlike a regular iterator's operator,
here it does not need to return a native reference to its own
instance, since it's the x::refiterator's
* that actually gets invoked, and
it returns a native reference to itself.
For input iterators, the required *
and the optional -> operators
need to return something that's convertible to the current
value referenced by the input iterator.
++()
x::refiterator's
++ method invokes the referenced
object's
++ operator, but returns a reference to
itself, and the return value from the object's
++ operator gets ignored.
The object's ++ operator's semantics
should implement the prefix version of the operator.
before_postoper()
x::refiterator's postfix version of
++ method invokes
before_postoper(), and passes through
whatever value it returns; but before returning, the
object's ++() gets invoked.
So, the sequence of events is:
x::refiterator's postfix
++ gets invoked.
The object's before_postoper()
gets invoked.
The object's ++() operator
gets invoked.
The return value from
before_postoper() becomes the
return value of
x::refiterator's
postfix ++() operator.
It follows that the return value from
before_postoper is expected to
be dereferenced by *(), in the context
of an input or an output iterator.