
[section:facade_tutorial Tutorial]

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 
[@http://thread.gmane.org/gmane.comp.lib.boost.user/5100 `posting`]
by Keith Macdonald on the 
[@http://www.boost.org/more/mailing_lists.htm#users `Boost-Users`]
mailing list.


[h2 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.

[h2 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<...>
  {
     ...
  };



[h2 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`.


[h3 `Derived`]

Because `iterator_facade` is meant to be used with the CRTP
[Cop95]_ the first parameter is the iterator class name itself,
`node_iterator`.

[h3 `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`.


[h3 `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`.

[h3 `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`.

[h3 `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
      >
  {
     ...
  };


[h2 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.

[h2 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;
  };

Voila; a complete and conforming readable, forward-traversal
iterator!  For a working example of its use, see 
[@../example/node_iterator1.cpp `this program`].

__ ../example/node_iterator1.cpp

[h2 A constant `node_iterator`]

[blurb *Constant and Mutable iterators*\n\n
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.\n\n  
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.\n\n
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:

  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;
  };

[blurb `const` and an iterator's `value_type`\n\n
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;


[h2 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 
[@../example/node_iterator2.cpp `here`].


[h2 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>

    ...

  private: 
    struct enabler {};

  public:
    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


[h2 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

[endsect]
