forked from boostorg/iterator
This commit was manufactured by cvs2svn to create branch 'RC_1_31_0'.
[SVN r21755]
This commit is contained in:
53
doc/facade_iterator_category.rst
Executable file
53
doc/facade_iterator_category.rst
Executable file
@ -0,0 +1,53 @@
|
||||
.. |iterator-category| replace:: *iterator-category*
|
||||
.. _iterator-category:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
*iterator-category*\ (C,R,V) :=
|
||||
if (C is convertible to std::input_iterator_tag
|
||||
|| C is convertible to std::output_iterator_tag
|
||||
)
|
||||
return C
|
||||
|
||||
else if (C is not convertible to incrementable_traversal_tag)
|
||||
*the program is ill-formed*
|
||||
|
||||
else return a type X satisfying the following two constraints:
|
||||
|
||||
1. X is convertible to X1, and not to any more-derived
|
||||
type, where X1 is defined by:
|
||||
|
||||
if (R is a reference type
|
||||
&& C is convertible to forward_traversal_tag)
|
||||
{
|
||||
if (C is convertible to random_access_traversal_tag)
|
||||
X1 = random_access_iterator_tag
|
||||
else if (C is convertible to bidirectional_traversal_tag)
|
||||
X1 = bidirectional_iterator_tag
|
||||
else
|
||||
X1 = forward_iterator_tag
|
||||
}
|
||||
else
|
||||
{
|
||||
if (C is convertible to single_pass_traversal_tag
|
||||
&& R is convertible to V)
|
||||
X1 = input_iterator_tag
|
||||
else
|
||||
X1 = C
|
||||
}
|
||||
|
||||
2. |category-to-traversal|_\ (X) is convertible to the most
|
||||
derived traversal tag type to which X is also
|
||||
convertible, and not to any more-derived traversal tag
|
||||
type.
|
||||
|
||||
.. |category-to-traversal| replace:: *category-to-traversal*
|
||||
.. _`category-to-traversal`: new-iter-concepts.html#category-to-traversal
|
||||
|
||||
[Note: the intention is to allow ``iterator_category`` to be one of
|
||||
the five original category tags when convertibility to one of the
|
||||
traversal tags would add no information]
|
||||
|
||||
.. Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
.. subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
29
doc/indirect_reference_ref.rst
Executable file
29
doc/indirect_reference_ref.rst
Executable file
@ -0,0 +1,29 @@
|
||||
.. Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
.. subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
::
|
||||
|
||||
template <class Dereferenceable>
|
||||
struct indirect_reference
|
||||
{
|
||||
typedef /* see below */ type;
|
||||
};
|
||||
|
||||
:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x``
|
||||
is well-formed. If ``++x`` is ill-formed it shall neither be
|
||||
ambiguous nor shall it violate access control, and
|
||||
``pointee<Dereferenceable>::type&`` shall be well-formed.
|
||||
Otherwise ``iterator_traits<Dereferenceable>::reference`` shall
|
||||
be well formed. [Note: These requirements need not apply to
|
||||
explicit or partial specializations of ``indirect_reference``]
|
||||
|
||||
``type`` is determined according to the following algorithm, where
|
||||
``x`` is an object of type ``Dereferenceable``::
|
||||
|
||||
if ( ++x is ill-formed )
|
||||
return ``pointee<Dereferenceable>::type&``
|
||||
else
|
||||
std::iterator_traits<Dereferenceable>::reference
|
||||
|
||||
|
131
doc/iterator_adaptor_tutorial.rst
Executable file
131
doc/iterator_adaptor_tutorial.rst
Executable file
@ -0,0 +1,131 @@
|
||||
.. Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
.. subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
In this section we'll further refine the ``node_iter`` class
|
||||
template we developed in the |fac_tut|_. If you haven't already
|
||||
read that material, you should go back now and check it out because
|
||||
we're going to pick up right where it left off.
|
||||
|
||||
.. |fac_tut| replace:: ``iterator_facade`` tutorial
|
||||
.. _fac_tut: iterator_facade.html#tutorial-example
|
||||
|
||||
.. sidebar:: ``node_base*`` really *is* an iterator
|
||||
|
||||
It's not really a very interesting iterator, since ``node_base``
|
||||
is an abstract class: a pointer to a ``node_base`` just points
|
||||
at some base subobject of an instance of some other class, and
|
||||
incrementing a ``node_base*`` moves it past this base subobject
|
||||
to who-knows-where? The most we can do with that incremented
|
||||
position is to compare another ``node_base*`` to it. In other
|
||||
words, the original iterator traverses a one-element array.
|
||||
|
||||
You probably didn't think of it this way, but the ``node_base*``
|
||||
object which underlies ``node_iterator`` is itself an iterator,
|
||||
just like all other pointers. If we examine that pointer closely
|
||||
from an iterator perspective, we can see that it has much in common
|
||||
with the ``node_iterator`` we're building. First, they share most
|
||||
of the same associated types (``value_type``, ``reference``,
|
||||
``pointer``, and ``difference_type``). Second, even some of the
|
||||
core functionality is the same: ``operator*`` and ``operator==`` on
|
||||
the ``node_iterator`` return the result of invoking the same
|
||||
operations on the underlying pointer, via the ``node_iterator``\ 's
|
||||
|dereference_and_equal|_). However, the ``operator++`` for
|
||||
``node_iterator`` behaves differently than for ``node_base*``
|
||||
since it follows the ``m_next`` pointer.
|
||||
|
||||
.. |dereference_and_equal| replace:: ``dereference`` and ``equal`` member functions
|
||||
.. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations
|
||||
|
||||
It turns out that the pattern of building an iterator on another
|
||||
iterator-like type (the ``Base`` [#base]_ type) while modifying
|
||||
just a few aspects of the underlying type's behavior is an
|
||||
extremely common one, and it's the pattern addressed by
|
||||
``iterator_adaptor``. Using ``iterator_adaptor`` is very much like
|
||||
using ``iterator_facade``, but because iterator_adaptor tries to
|
||||
mimic as much of the ``Base`` type's behavior as possible, we
|
||||
neither have to supply a ``Value`` argument, nor implement any core
|
||||
behaviors other than ``increment``. The implementation of
|
||||
``node_iter`` is thus reduced to::
|
||||
|
||||
template <class Value>
|
||||
class node_iter
|
||||
: public boost::iterator_adaptor<
|
||||
node_iter<Value> // Derived
|
||||
, Value* // Base
|
||||
, boost::use_default // Value
|
||||
, boost::forward_traversal_tag // CategoryOrTraversal
|
||||
>
|
||||
{
|
||||
private:
|
||||
struct enabler {}; // a private type avoids misuse
|
||||
|
||||
typedef boost::iterator_adaptor<
|
||||
node_iter<Value>, Value*, boost::use_default, boost::forward_traversal_tag
|
||||
> super_t;
|
||||
|
||||
public:
|
||||
node_iter()
|
||||
: super_t(0) {}
|
||||
|
||||
explicit node_iter(Value* p)
|
||||
: super_t(p) {}
|
||||
|
||||
template <class OtherValue>
|
||||
node_iter(
|
||||
node_iter<OtherValue> const& other
|
||||
, typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: super_t(other.base()) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
void increment() { this->base_reference() = this->base()->next(); }
|
||||
};
|
||||
|
||||
You can see an example program which exercises this version of the
|
||||
node iterators `here`__.
|
||||
|
||||
__ ../example/node_iterator3.cpp
|
||||
|
||||
In the case of ``node_iter``, it's not very compelling to pass
|
||||
``boost::use_default`` as ``iterator_adaptor``\ 's ``Value``
|
||||
argument; we could have just passed ``node_iter``\ 's ``Value``
|
||||
along to ``iterator_adaptor``, and that'd even be shorter! Most
|
||||
iterator class templates built with ``iterator_adaptor`` are
|
||||
parameterized on another iterator type, rather than on its
|
||||
``value_type``. For example, ``boost::reverse_iterator`` takes an
|
||||
iterator type argument and reverses its direction of traversal,
|
||||
since the original iterator and the reversed one have all the same
|
||||
associated types, ``iterator_adaptor``\ 's delegation of default
|
||||
types to its ``Base`` saves the implementor of
|
||||
``boost::reverse_iterator`` from writing
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
std::iterator_traits<Iterator>::*some-associated-type*
|
||||
|
||||
at least four times.
|
||||
|
||||
We urge you to review the documentation and implementations of
|
||||
|reverse_iterator|_ and the other Boost `specialized iterator
|
||||
adaptors`__ to get an idea of the sorts of things you can do with
|
||||
``iterator_adaptor``. In particular, have a look at
|
||||
|transform_iterator|_, which is perhaps the most straightforward
|
||||
adaptor, and also |counting_iterator|_, which demonstrates that
|
||||
``iterator_adaptor``\ 's ``Base`` type needn't be an iterator.
|
||||
|
||||
.. |reverse_iterator| replace:: ``reverse_iterator``
|
||||
.. _reverse_iterator: reverse_iterator.html
|
||||
|
||||
.. |counting_iterator| replace:: ``counting_iterator``
|
||||
.. _counting_iterator: counting_iterator.html
|
||||
|
||||
.. |transform_iterator| replace:: ``transform_iterator``
|
||||
.. _transform_iterator: transform_iterator.html
|
||||
|
||||
__ index.html#specialized-adaptors
|
||||
|
519
doc/iterator_facade_tutorial.rst
Executable file
519
doc/iterator_facade_tutorial.rst
Executable file
@ -0,0 +1,519 @@
|
||||
.. Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
.. subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
In this section we'll walk through the implementation of a few
|
||||
iterators using ``iterator_facade``, based around the simple
|
||||
example of a linked list of polymorphic objects. This example was
|
||||
inspired by a `posting`__ by Keith Macdonald on the `Boost-Users`_
|
||||
mailing list.
|
||||
|
||||
.. _`Boost-Users`: ../../../more/mailing_lists.htm#users
|
||||
|
||||
__ http://thread.gmane.org/gmane.comp.lib.boost.user/5100
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
Say we've written a polymorphic linked list node base class::
|
||||
|
||||
# include <iostream>
|
||||
|
||||
struct node_base
|
||||
{
|
||||
node_base() : m_next(0) {}
|
||||
|
||||
// Each node manages all of its tail nodes
|
||||
virtual ~node_base() { delete m_next; }
|
||||
|
||||
// Access the rest of the list
|
||||
node_base* next() const { return m_next; }
|
||||
|
||||
// print to the stream
|
||||
virtual void print(std::ostream& s) const = 0;
|
||||
|
||||
// double the value
|
||||
virtual void double_me() = 0;
|
||||
|
||||
void append(node_base* p)
|
||||
{
|
||||
if (m_next)
|
||||
m_next->append(p);
|
||||
else
|
||||
m_next = p;
|
||||
}
|
||||
|
||||
private:
|
||||
node_base* m_next;
|
||||
};
|
||||
|
||||
Lists can hold objects of different types by linking together
|
||||
specializations of the following template::
|
||||
|
||||
template <class T>
|
||||
struct node : node_base
|
||||
{
|
||||
node(T x)
|
||||
: m_value(x)
|
||||
{}
|
||||
|
||||
void print(std::ostream& s) const { s << this->m_value; }
|
||||
void double_me() { m_value += m_value; }
|
||||
|
||||
private:
|
||||
T m_value;
|
||||
};
|
||||
|
||||
And we can print any node using the following streaming operator::
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, node_base const& n)
|
||||
{
|
||||
n.print(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Our first challenge is to build an appropriate iterator over these
|
||||
lists.
|
||||
|
||||
A Basic Iterator Using ``iterator_facade``
|
||||
------------------------------------------
|
||||
|
||||
We will construct a ``node_iterator`` class using inheritance from
|
||||
``iterator_facade`` to implement most of the iterator's operations.
|
||||
|
||||
::
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<...>
|
||||
{
|
||||
...
|
||||
};
|
||||
|
||||
|
||||
|
||||
Template Arguments for ``iterator_facade``
|
||||
..........................................
|
||||
|
||||
``iterator_facade`` has several template parameters, so we must decide
|
||||
what types to use for the arguments. The parameters are ``Derived``,
|
||||
``Value``, ``CategoryOrTraversal``, ``Reference``, and ``Difference``.
|
||||
|
||||
|
||||
``Derived``
|
||||
'''''''''''
|
||||
|
||||
Because ``iterator_facade`` is meant to be used with the CRTP
|
||||
[Cop95]_ the first parameter is the iterator class name itself,
|
||||
``node_iterator``.
|
||||
|
||||
``Value``
|
||||
'''''''''
|
||||
|
||||
The ``Value`` parameter determines the ``node_iterator``\ 's
|
||||
``value_type``. In this case, we are iterating over ``node_base``
|
||||
objects, so ``Value`` will be ``node_base``.
|
||||
|
||||
|
||||
``CategoryOrTraversal``
|
||||
'''''''''''''''''''''''
|
||||
|
||||
Now we have to determine which `iterator traversal concept`_ our
|
||||
``node_iterator`` is going to model. Singly-linked lists only have
|
||||
forward links, so our iterator can't can't be a `bidirectional
|
||||
traversal iterator`_. Our iterator should be able to make multiple
|
||||
passes over the same linked list (unlike, say, an
|
||||
``istream_iterator`` which consumes the stream it traverses), so it
|
||||
must be a `forward traversal iterator`_. Therefore, we'll pass
|
||||
``boost::forward_traversal_tag`` in this position [#category]_.
|
||||
|
||||
.. [#category] ``iterator_facade`` also supports old-style category
|
||||
tags, so we could have passed ``std::forward_iterator_tag`` here;
|
||||
either way, the resulting iterator's ``iterator_category`` will
|
||||
end up being ``std::forward_iterator_tag``.
|
||||
|
||||
``Reference``
|
||||
'''''''''''''
|
||||
|
||||
The ``Reference`` argument becomes the type returned by
|
||||
``node_iterator``\ 's dereference operation, and will also be the
|
||||
same as ``std::iterator_traits<node_iterator>::reference``. The
|
||||
library's default for this parameter is ``Value&``; since
|
||||
``node_base&`` is a good choice for the iterator's ``reference``
|
||||
type, we can omit this argument, or pass ``use_default``.
|
||||
|
||||
``Difference``
|
||||
''''''''''''''
|
||||
|
||||
The ``Difference`` argument determines how the distance between
|
||||
two ``node_iterator``\ s will be measured and will also be the
|
||||
same as ``std::iterator_traits<node_iterator>::difference_type``.
|
||||
The library's default for ``Difference`` is ``std::ptrdiff_t``, an
|
||||
appropriate type for measuring the distance between any two
|
||||
addresses in memory, and one that works for almost any iterator,
|
||||
so we can omit this argument, too.
|
||||
|
||||
The declaration of ``node_iterator`` will therefore look something
|
||||
like::
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator
|
||||
, node_base
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
...
|
||||
};
|
||||
|
||||
Constructors and Data Members
|
||||
.............................
|
||||
|
||||
Next we need to decide how to represent the iterator's position.
|
||||
This representation will take the form of data members, so we'll
|
||||
also need to write constructors to initialize them. The
|
||||
``node_iterator``\ 's position is quite naturally represented using
|
||||
a pointer to a ``node_base``. We'll need a constructor to build an
|
||||
iterator from a ``node_base*``, and a default constructor to
|
||||
satisfy the `forward traversal iterator`_ requirements [#default]_.
|
||||
Our ``node_iterator`` then becomes::
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator
|
||||
, node_base
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
node_iterator()
|
||||
: m_node(0)
|
||||
{}
|
||||
|
||||
explicit node_iterator(node_base* p)
|
||||
: m_node(p)
|
||||
{}
|
||||
|
||||
private:
|
||||
...
|
||||
node_base* m_node;
|
||||
};
|
||||
|
||||
.. [#default] Technically, the C++ standard places almost no
|
||||
requirements on a default-constructed iterator, so if we were
|
||||
really concerned with efficiency, we could've written the
|
||||
default constructor to leave ``m_node`` uninitialized.
|
||||
|
||||
Implementing the Core Operations
|
||||
................................
|
||||
|
||||
The last step is to implement the `core operations`_ required by
|
||||
the concepts we want our iterator to model. Referring to the
|
||||
table__, we can see that the first three rows are applicable
|
||||
because ``node_iterator`` needs to satisfy the requirements for
|
||||
`readable iterator`_, `single pass iterator`_, and `incrementable
|
||||
iterator`_.
|
||||
|
||||
__ `core operations`_
|
||||
|
||||
We therefore need to supply ``dereference``,
|
||||
``equal``, and ``increment`` members. We don't want these members
|
||||
to become part of ``node_iterator``\ 's public interface, so we can
|
||||
make them private and grant friendship to
|
||||
``boost::iterator_core_access``, a "back-door" that
|
||||
``iterator_facade`` uses to get access to the core operations::
|
||||
|
||||
# include "node.hpp"
|
||||
# include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
class node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator
|
||||
, node_base
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
node_iterator()
|
||||
: m_node(0) {}
|
||||
|
||||
explicit node_iterator(node_base* p)
|
||||
: m_node(p) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void increment() { m_node = m_node->next(); }
|
||||
|
||||
bool equal(node_iterator const& other) const
|
||||
{
|
||||
return this->m_node == other.m_node;
|
||||
}
|
||||
|
||||
node_base& dereference() const { return *m_node; }
|
||||
|
||||
node_base* m_node;
|
||||
};
|
||||
|
||||
Voil<EFBFBD>; a complete and conforming readable, forward-traversal
|
||||
iterator! For a working example of its use, see `this program`__.
|
||||
|
||||
__ ../example/node_iterator1.cpp
|
||||
|
||||
A constant ``node_iterator``
|
||||
----------------------------
|
||||
|
||||
.. Sidebar:: Constant and Mutable iterators
|
||||
|
||||
The term **mutable iterator** means an iterator through which
|
||||
the object it references (its "referent") can be modified. A
|
||||
**constant iterator** is one which doesn't allow modification of
|
||||
its referent.
|
||||
|
||||
The words *constant* and *mutable* don't refer to the ability to
|
||||
modify the iterator itself. For example, an ``int const*`` is a
|
||||
non-\ ``const`` *constant iterator*, which can be incremented
|
||||
but doesn't allow modification of its referent, and ``int*
|
||||
const`` is a ``const`` *mutable iterator*, which cannot be
|
||||
modified but which allows modification of its referent.
|
||||
|
||||
Confusing? We agree, but those are the standard terms. It
|
||||
probably doesn't help much that a container's constant iterator
|
||||
is called ``const_iterator``.
|
||||
|
||||
Now, our ``node_iterator`` gives clients access to both ``node``\
|
||||
's ``print(std::ostream&) const`` member function, but also its
|
||||
mutating ``double_me()`` member. If we wanted to build a
|
||||
*constant* ``node_iterator``, we'd only have to make three
|
||||
changes:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
class const_node_iterator
|
||||
: public boost::iterator_facade<
|
||||
node_iterator
|
||||
, node_base **const**
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
const_node_iterator()
|
||||
: m_node(0) {}
|
||||
|
||||
explicit const_node_iterator(node_base* p)
|
||||
: m_node(p) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
void increment() { m_node = m_node->next(); }
|
||||
|
||||
bool equal(const_node_iterator const& other) const
|
||||
{
|
||||
return this->m_node == other.m_node;
|
||||
}
|
||||
|
||||
node_base **const**\ & dereference() const { return \*m_node; }
|
||||
|
||||
node_base **const**\ * m_node;
|
||||
};
|
||||
|
||||
.. Sidebar:: ``const`` and an iterator's ``value_type``
|
||||
|
||||
The C++ standard requires an iterator's ``value_type`` *not* be
|
||||
``const``\ -qualified, so ``iterator_facade`` strips the
|
||||
``const`` from its ``Value`` parameter in order to produce the
|
||||
iterator's ``value_type``. Making the ``Value`` argument
|
||||
``const`` provides a useful hint to ``iterator_facade`` that the
|
||||
iterator is a *constant iterator*, and the default ``Reference``
|
||||
argument will be correct for all lvalue iterators.
|
||||
|
||||
As a matter of fact, ``node_iterator`` and ``const_node_iterator``
|
||||
are so similar that it makes sense to factor the common code out
|
||||
into a template as follows::
|
||||
|
||||
template <class Value>
|
||||
class node_iter
|
||||
: public boost::iterator_facade<
|
||||
node_iter<Value>
|
||||
, Value
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
node_iter()
|
||||
: m_node(0) {}
|
||||
|
||||
explicit node_iter(Value* p)
|
||||
: m_node(p) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
bool equal(node_iter<Value> const& other) const
|
||||
{
|
||||
return this->m_node == other.m_node;
|
||||
}
|
||||
|
||||
void increment()
|
||||
{ m_node = m_node->next(); }
|
||||
|
||||
Value& dereference() const
|
||||
{ return *m_node; }
|
||||
|
||||
Value* m_node;
|
||||
};
|
||||
typedef node_iter<node_base> node_iterator;
|
||||
typedef node_iter<node_base const> node_const_iterator;
|
||||
|
||||
|
||||
Interoperability
|
||||
----------------
|
||||
|
||||
Our ``const_node_iterator`` works perfectly well on its own, but
|
||||
taken together with ``node_iterator`` it doesn't quite meet
|
||||
expectations. For example, we'd like to be able to pass a
|
||||
``node_iterator`` where a ``node_const_iterator`` was expected,
|
||||
just as you can with ``std::list<int>``\ 's ``iterator`` and
|
||||
``const_iterator``. Furthermore, given a ``node_iterator`` and a
|
||||
``node_const_iterator`` into the same list, we should be able to
|
||||
compare them for equality.
|
||||
|
||||
This expected ability to use two different iterator types together
|
||||
is known as |interoperability|_. Achieving interoperability in
|
||||
our case is as simple as templatizing the ``equal`` function and
|
||||
adding a templatized converting constructor [#broken]_ [#random]_::
|
||||
|
||||
template <class Value>
|
||||
class node_iter
|
||||
: public boost::iterator_facade<
|
||||
node_iter<Value>
|
||||
, Value
|
||||
, boost::forward_traversal_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
node_iter()
|
||||
: m_node(0) {}
|
||||
|
||||
explicit node_iter(Value* p)
|
||||
: m_node(p) {}
|
||||
|
||||
template <class OtherValue>
|
||||
node_iter(node_iter<OtherValue> const& other)
|
||||
: m_node(other.m_node) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
template <class> friend class node_iter;
|
||||
|
||||
template <class OtherValue>
|
||||
bool equal(node_iter<OtherValue> const& other) const
|
||||
{
|
||||
return this->m_node == other.m_node;
|
||||
}
|
||||
|
||||
void increment()
|
||||
{ m_node = m_node->next(); }
|
||||
|
||||
Value& dereference() const
|
||||
{ return *m_node; }
|
||||
|
||||
Value* m_node;
|
||||
};
|
||||
typedef impl::node_iterator<node_base> node_iterator;
|
||||
typedef impl::node_iterator<node_base const> node_const_iterator;
|
||||
|
||||
.. |interoperability| replace:: **interoperability**
|
||||
.. _interoperability: new-iter-concepts.html#interoperable-iterators-lib-interoperable-iterators
|
||||
|
||||
.. [#broken] If you're using an older compiler and it can't handle
|
||||
this example, see the `example code`__ for workarounds.
|
||||
|
||||
.. [#random] If ``node_iterator`` had been a `random access
|
||||
traversal iterator`_, we'd have had to templatize its
|
||||
``distance_to`` function as well.
|
||||
|
||||
|
||||
__ ../example/node_iterator2.hpp
|
||||
|
||||
You can see an example program which exercises our interoperable
|
||||
iterators `here`__.
|
||||
|
||||
__ ../example/node_iterator2.cpp
|
||||
|
||||
Telling the Truth
|
||||
-----------------
|
||||
|
||||
Now ``node_iterator`` and ``node_const_iterator`` behave exactly as
|
||||
you'd expect... almost. We can compare them and we can convert in
|
||||
one direction: from ``node_iterator`` to ``node_const_iterator``.
|
||||
If we try to convert from ``node_const_iterator`` to
|
||||
``node_iterator``, we'll get an error when the converting
|
||||
constructor tries to initialize ``node_iterator``\ 's ``m_node``, a
|
||||
``node*`` with a ``node const*``. So what's the problem?
|
||||
|
||||
The problem is that
|
||||
``boost::``\ |is_convertible|_\ ``<node_const_iterator,node_iterator>::value``
|
||||
will be ``true``, but it should be ``false``. |is_convertible|_
|
||||
lies because it can only see as far as the *declaration* of
|
||||
``node_iter``\ 's converting constructor, but can't look inside at
|
||||
the *definition* to make sure it will compile. A perfect solution
|
||||
would make ``node_iter``\ 's converting constructor disappear when
|
||||
the ``m_node`` conversion would fail.
|
||||
|
||||
.. |is_convertible| replace:: ``is_convertible``
|
||||
.. _is_convertible: ../../type_traits/index.html#relationships
|
||||
|
||||
In fact, that sort of magic is possible using
|
||||
|enable_if|__. By rewriting the converting constructor as
|
||||
follows, we can remove it from the overload set when it's not
|
||||
appropriate::
|
||||
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
...
|
||||
|
||||
template <class OtherValue>
|
||||
node_iter(
|
||||
node_iter<OtherValue> const& other
|
||||
, typename boost::enable_if<
|
||||
boost::is_convertible<OtherValue*,Value*>
|
||||
, enabler
|
||||
>::type = enabler()
|
||||
)
|
||||
: m_node(other.m_node) {}
|
||||
|
||||
.. |enable_if| replace:: ``boost::enable_if``
|
||||
__ ../../utility/enable_if.html
|
||||
|
||||
|
||||
Wrap Up
|
||||
-------
|
||||
|
||||
This concludes our ``iterator_facade`` tutorial, but before you
|
||||
stop reading we urge you to take a look at |iterator_adaptor|__.
|
||||
There's another way to approach writing these iterators which might
|
||||
even be superior.
|
||||
|
||||
.. |iterator_adaptor| replace:: ``iterator_adaptor``
|
||||
__ iterator_adaptor.html
|
||||
|
||||
.. _`iterator traversal concept`: new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal
|
||||
.. _`readable iterator`: new-iter-concepts.html#readable-iterators-lib-readable-iterators
|
||||
.. _`lvalue iterator`: new-iter-concepts.html#lvalue-iterators-lib-lvalue-iterators
|
||||
.. _`single pass iterator`: new-iter-concepts.html#single-pass-iterators-lib-single-pass-iterators
|
||||
.. _`incrementable iterator`: new-iter-concepts.html#incrementable-iterators-lib-incrementable-iterators
|
||||
.. _`forward traversal iterator`: new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators
|
||||
.. _`bidirectional traversal iterator`: new-iter-concepts.html#bidirectional-traversal-iterators-lib-bidirectional-traversal-iterators
|
||||
.. _`random access traversal iterator`: new-iter-concepts.html#random-access-traversal-iterators-lib-random-access-traversal-iterators
|
||||
|
16
doc/make_filter_iterator.rst
Executable file
16
doc/make_filter_iterator.rst
Executable file
@ -0,0 +1,16 @@
|
||||
|
||||
::
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
filter_iterator<Predicate,Iterator>
|
||||
make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
|
||||
|
||||
:Returns: filter_iterator<Predicate,Iterator>(f, x, end)
|
||||
|
||||
::
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
filter_iterator<Predicate,Iterator>
|
||||
make_filter_iterator(Iterator x, Iterator end = Iterator());
|
||||
|
||||
:Returns: filter_iterator<Predicate,Iterator>(x, end)
|
179
doc/pointee.html
Executable file
179
doc/pointee.html
Executable file
@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.3.1: http://docutils.sourceforge.net/" />
|
||||
<title>pointee and indirect_reference</title>
|
||||
<meta name="author" content="David Abrahams" />
|
||||
<meta name="organization" content="Boost Consulting" />
|
||||
<meta name="date" content="2004-01-13" />
|
||||
<meta name="copyright" content="Copyright David Abrahams 2004. All rights reserved" />
|
||||
<link rel="stylesheet" href="default.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="pointee-and-indirect-reference">
|
||||
<h1 class="title"><tt class="literal"><span class="pre">pointee</span></tt> and <tt class="literal"><span class="pre">indirect_reference</span></tt></h1>
|
||||
<table class="docinfo" frame="void" rules="none">
|
||||
<col class="docinfo-name" />
|
||||
<col class="docinfo-content" />
|
||||
<tbody valign="top">
|
||||
<tr><th class="docinfo-name">Author:</th>
|
||||
<td>David Abrahams</td></tr>
|
||||
<tr><th class="docinfo-name">Contact:</th>
|
||||
<td><a class="first reference" href="mailto:dave@boost-consulting.com">dave@boost-consulting.com</a>, <a class="reference" href="mailto:jsiek@osl.iu.edu">jsiek@osl.iu.edu</a>, <a class="last reference" href="mailto:witt@ive.uni-hannover.de">witt@ive.uni-hannover.de</a></td></tr>
|
||||
<tr><th class="docinfo-name">Organization:</th>
|
||||
<td><a class="first last reference" href="http://www.boost-consulting.com">Boost Consulting</a></td></tr>
|
||||
<tr><th class="docinfo-name">Date:</th>
|
||||
<td>2004-01-13</td></tr>
|
||||
<tr><th class="docinfo-name">Copyright:</th>
|
||||
<td>Copyright David Abrahams 2004. All rights reserved</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field"><th class="field-name">abstract:</th><td class="field-body">Provides the capability to deduce the referent types of
|
||||
pointers, smart pointers and iterators in generic code.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="section" id="overview">
|
||||
<h1><a name="overview">Overview</a></h1>
|
||||
<p>Have you ever wanted to write a generic function that can operate
|
||||
on any kind of dereferenceable object? If you have, you've
|
||||
probably run into the problem of how to determine the type that the
|
||||
object "points at":</p>
|
||||
<pre class="literal-block">
|
||||
template <class Dereferenceable>
|
||||
void f(Dereferenceable p)
|
||||
{
|
||||
<em>what-goes-here?</em> value = *p;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<div class="section" id="pointee">
|
||||
<h2><a name="pointee"><tt class="literal"><span class="pre">pointee</span></tt></a></h2>
|
||||
<p>It turns out to be impossible to come up with a fully-general
|
||||
algorithm to do determine <em>what-goes-here</em> directly, but it is
|
||||
possible to require that <tt class="literal"><span class="pre">pointee<Dereferenceable>::type</span></tt> is
|
||||
correct. Naturally, <tt class="literal"><span class="pre">pointee</span></tt> has the same difficulty: it can't
|
||||
determine the appropriate <tt class="literal"><span class="pre">::type</span></tt> reliably for all
|
||||
<tt class="literal"><span class="pre">Dereferenceable</span></tt>s, but it makes very good guesses (it works
|
||||
for all pointers, standard and boost smart pointers, and
|
||||
iterators), and when it guesses wrongly, it can be specialized as
|
||||
neccessary:</p>
|
||||
<pre class="literal-block">
|
||||
namespace boost
|
||||
{
|
||||
template <class T>
|
||||
struct pointee<third_party_lib::smart_pointer<T> >
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="indirect-reference">
|
||||
<h2><a name="indirect-reference"><tt class="literal"><span class="pre">indirect_reference</span></tt></a></h2>
|
||||
<p><tt class="literal"><span class="pre">indirect_reference<T>::type</span></tt> is rather more specialized than
|
||||
<tt class="literal"><span class="pre">pointee</span></tt>, and is meant to be used to forward the result of
|
||||
dereferencing an object of its argument type. Most dereferenceable
|
||||
types just return a reference to their pointee, but some return
|
||||
proxy references or return the pointee by value. When that
|
||||
information is needed, call on <tt class="literal"><span class="pre">indirect_reference</span></tt>.</p>
|
||||
<p>Both of these templates are essential to the correct functioning of
|
||||
<a class="reference" href="indirect_iterator.html"><tt class="literal"><span class="pre">indirect_iterator</span></tt></a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="reference">
|
||||
<h1><a name="reference">Reference</a></h1>
|
||||
<div class="section" id="id1">
|
||||
<h2><a name="id1"><tt class="literal"><span class="pre">pointee</span></tt></a></h2>
|
||||
<!-- Copyright David Abrahams 2004. Use, modification and distribution is -->
|
||||
<!-- subject to the Boost Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<pre class="literal-block">
|
||||
template <class Dereferenceable>
|
||||
struct pointee
|
||||
{
|
||||
typedef /* see below */ type;
|
||||
};
|
||||
</pre>
|
||||
<table class="field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field"><th class="field-name">Requires:</th><td class="field-body">For an object <tt class="literal"><span class="pre">x</span></tt> of type <tt class="literal"><span class="pre">Dereferenceable</span></tt>, <tt class="literal"><span class="pre">*x</span></tt>
|
||||
is well-formed. If <tt class="literal"><span class="pre">++x</span></tt> is ill-formed it shall neither be
|
||||
ambiguous nor shall it violate access control, and
|
||||
<tt class="literal"><span class="pre">Dereferenceable::element_type</span></tt> shall be an accessible type.
|
||||
Otherwise <tt class="literal"><span class="pre">iterator_traits<Dereferenceable>::value_type</span></tt> shall
|
||||
be well formed. [Note: These requirements need not apply to
|
||||
explicit or partial specializations of <tt class="literal"><span class="pre">pointee</span></tt>]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><tt class="literal"><span class="pre">type</span></tt> is determined according to the following algorithm, where
|
||||
<tt class="literal"><span class="pre">x</span></tt> is an object of type <tt class="literal"><span class="pre">Dereferenceable</span></tt>:</p>
|
||||
<pre class="literal-block">
|
||||
if ( ++x is ill-formed )
|
||||
{
|
||||
return ``Dereferenceable::element_type``
|
||||
}
|
||||
else if (``*x`` is a mutable reference to
|
||||
std::iterator_traits<Dereferenceable>::value_type)
|
||||
{
|
||||
return iterator_traits<Dereferenceable>::value_type
|
||||
}
|
||||
else
|
||||
{
|
||||
return iterator_traits<Dereferenceable>::value_type const
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="id2">
|
||||
<h2><a name="id2"><tt class="literal"><span class="pre">indirect_reference</span></tt></a></h2>
|
||||
<!-- Copyright David Abrahams 2004. Use, modification and distribution is -->
|
||||
<!-- subject to the Boost Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<pre class="literal-block">
|
||||
template <class Dereferenceable>
|
||||
struct indirect_reference
|
||||
{
|
||||
typedef /* see below */ type;
|
||||
};
|
||||
</pre>
|
||||
<table class="field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field"><th class="field-name">Requires:</th><td class="field-body">For an object <tt class="literal"><span class="pre">x</span></tt> of type <tt class="literal"><span class="pre">Dereferenceable</span></tt>, <tt class="literal"><span class="pre">*x</span></tt>
|
||||
is well-formed. If <tt class="literal"><span class="pre">++x</span></tt> is ill-formed it shall neither be
|
||||
ambiguous nor shall it violate access control, and
|
||||
<tt class="literal"><span class="pre">pointee<Dereferenceable>::type&</span></tt> shall be well-formed.
|
||||
Otherwise <tt class="literal"><span class="pre">iterator_traits<Dereferenceable>::reference</span></tt> shall
|
||||
be well formed. [Note: These requirements need not apply to
|
||||
explicit or partial specializations of <tt class="literal"><span class="pre">indirect_reference</span></tt>]</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><tt class="literal"><span class="pre">type</span></tt> is determined according to the following algorithm, where
|
||||
<tt class="literal"><span class="pre">x</span></tt> is an object of type <tt class="literal"><span class="pre">Dereferenceable</span></tt>:</p>
|
||||
<pre class="literal-block">
|
||||
if ( ++x is ill-formed )
|
||||
return ``pointee<Dereferenceable>::type&``
|
||||
else
|
||||
std::iterator_traits<Dereferenceable>::reference
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer" />
|
||||
<div class="footer">
|
||||
<a class="reference" href="pointee.rst">View document source</a>.
|
||||
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
84
doc/pointee.rst
Executable file
84
doc/pointee.rst
Executable file
@ -0,0 +1,84 @@
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
``pointee`` and ``indirect_reference``
|
||||
++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
:Author: David Abrahams
|
||||
:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
|
||||
:organization: `Boost Consulting`_
|
||||
:date: $Date$
|
||||
:copyright: Copyright David Abrahams 2004. All rights reserved
|
||||
|
||||
.. _`Boost Consulting`: http://www.boost-consulting.com
|
||||
|
||||
:abstract: Provides the capability to deduce the referent types of
|
||||
pointers, smart pointers and iterators in generic code.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Have you ever wanted to write a generic function that can operate
|
||||
on any kind of dereferenceable object? If you have, you've
|
||||
probably run into the problem of how to determine the type that the
|
||||
object "points at":
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
template <class Dereferenceable>
|
||||
void f(Dereferenceable p)
|
||||
{
|
||||
*what-goes-here?* value = \*p;
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
``pointee``
|
||||
-----------
|
||||
|
||||
It turns out to be impossible to come up with a fully-general
|
||||
algorithm to do determine *what-goes-here* directly, but it is
|
||||
possible to require that ``pointee<Dereferenceable>::type`` is
|
||||
correct. Naturally, ``pointee`` has the same difficulty: it can't
|
||||
determine the appropriate ``::type`` reliably for all
|
||||
``Dereferenceable``\ s, but it makes very good guesses (it works
|
||||
for all pointers, standard and boost smart pointers, and
|
||||
iterators), and when it guesses wrongly, it can be specialized as
|
||||
neccessary::
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class T>
|
||||
struct pointee<third_party_lib::smart_pointer<T> >
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
}
|
||||
|
||||
``indirect_reference``
|
||||
----------------------
|
||||
|
||||
``indirect_reference<T>::type`` is rather more specialized than
|
||||
``pointee``, and is meant to be used to forward the result of
|
||||
dereferencing an object of its argument type. Most dereferenceable
|
||||
types just return a reference to their pointee, but some return
|
||||
proxy references or return the pointee by value. When that
|
||||
information is needed, call on ``indirect_reference``.
|
||||
|
||||
Both of these templates are essential to the correct functioning of
|
||||
|indirect_iterator|_.
|
||||
|
||||
.. |indirect_iterator| replace:: ``indirect_iterator``
|
||||
.. _indirect_iterator: indirect_iterator.html
|
||||
|
||||
Reference
|
||||
=========
|
||||
|
||||
``pointee``
|
||||
-----------
|
||||
|
||||
.. include:: pointee_ref.rst
|
||||
|
||||
``indirect_reference``
|
||||
----------------------
|
||||
|
||||
.. include:: indirect_reference_ref.rst
|
||||
|
38
doc/pointee_ref.rst
Executable file
38
doc/pointee_ref.rst
Executable file
@ -0,0 +1,38 @@
|
||||
.. Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
.. subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
::
|
||||
|
||||
template <class Dereferenceable>
|
||||
struct pointee
|
||||
{
|
||||
typedef /* see below */ type;
|
||||
};
|
||||
|
||||
:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x``
|
||||
is well-formed. If ``++x`` is ill-formed it shall neither be
|
||||
ambiguous nor shall it violate access control, and
|
||||
``Dereferenceable::element_type`` shall be an accessible type.
|
||||
Otherwise ``iterator_traits<Dereferenceable>::value_type`` shall
|
||||
be well formed. [Note: These requirements need not apply to
|
||||
explicit or partial specializations of ``pointee``]
|
||||
|
||||
``type`` is determined according to the following algorithm, where
|
||||
``x`` is an object of type ``Dereferenceable``::
|
||||
|
||||
if ( ++x is ill-formed )
|
||||
{
|
||||
return ``Dereferenceable::element_type``
|
||||
}
|
||||
else if (``*x`` is a mutable reference to
|
||||
std::iterator_traits<Dereferenceable>::value_type)
|
||||
{
|
||||
return iterator_traits<Dereferenceable>::value_type
|
||||
}
|
||||
else
|
||||
{
|
||||
return iterator_traits<Dereferenceable>::value_type const
|
||||
}
|
||||
|
||||
|
7
doc/rst2html
Executable file
7
doc/rst2html
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
PYTHONPATH="c:/src/docutils/docutils;c:/src/docutils/docutils/extras"
|
||||
export PYTHONPATH
|
||||
python c:/src/docutils/docutils/tools/html.py -gs $1 `echo $1 | sed 's/\(.*\)\..*/\1.html/'`
|
||||
|
||||
|
||||
|
29
doc/scanrst.py
Normal file
29
doc/scanrst.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright David Abrahams 2004. Use, modification and distribution is
|
||||
# subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# This script accepts a list of .rst files to be processed and
|
||||
# generates Makefile dependencies for .html and .rst files to stdout.
|
||||
import os,sys
|
||||
import re
|
||||
|
||||
include = re.compile(r' *\.\. +(include|image):: +(.*)', re.MULTILINE)
|
||||
|
||||
def deps(path, found):
|
||||
dir = os.path.split(path)[0]
|
||||
for m in re.findall(include, open(path).read()):
|
||||
|
||||
dependency = os.path.normpath(os.path.join(dir,m[1]))
|
||||
if dependency not in found:
|
||||
found[dependency] = 1
|
||||
|
||||
if m[0] == 'include':
|
||||
deps(dependency, found)
|
||||
|
||||
return found
|
||||
|
||||
for file in sys.argv[1:]:
|
||||
found = deps(file, {})
|
||||
if found:
|
||||
base = os.path.splitext(os.path.basename(file))[0]
|
||||
print '%s.tex %s.html: %s' % (base, base, ' '.join(found.keys()))
|
Reference in New Issue
Block a user