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::ref
s and x::ptr
s, 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.