|  | Home | Libraries | People | FAQ | More | 
While the iterator interface is rich, there is a core subset of the interface that is necessary for all the functionality. We have identified the following core behaviors for iterators:
        In addition to the behaviors listed above, the core interface elements include
        the associated types exposed through iterator traits: value_type,
        reference, difference_type, and iterator_category.
      
        Iterator facade uses the Curiously Recurring Template Pattern (CRTP) [Cop95]_
        so that the user can specify the behavior of iterator_facade
        in a derived class. Former designs used policy objects to specify the behavior,
        but that approach was discarded for several reasons:
      
1. the creation and eventual copying of the policy object may create overhead that can be avoided with the current approach.
        2. The policy object approach does not allow for custom constructors on the
        created iterator types, an essential feature if iterator_facade
        should be used in other library implementations.
      
        3. Without the use of CRTP, the standard requirement that an iterator's
        operator++
        returns the iterator type itself would mean that all iterators built with
        the library would have to be specializations of iterator_facade<...>, rather than something more descriptive
        like indirect_iterator<T*>.
        Cumbersome type generator metafunctions would be needed to build new parameterized
        iterators, and a separate iterator_adaptor
        layer would be impossible.
      
        The user of iterator_facade
        derives his iterator class from a specialization of iterator_facade
        and passes the derived iterator class as iterator_facade's
        first template parameter. The order of the other template parameters have
        been carefully chosen to take advantage of useful defaults. For example,
        when defining a constant lvalue iterator, the user can pass a const-qualified
        version of the iterator's value_type
        as iterator_facade's Value parameter and omit the Reference parameter which follows.
      
The derived iterator class must define member functions implementing the iterator's core behaviors. The following table describes expressions which are required to be valid depending on the category of the derived iterator type. These member functions are described briefly below and in more detail in the iterator facade requirements.
Table 1.10. Core Interface
| Expression | Effects | 
|---|---|
| 
                   | Access the value referred to | 
| 
                   | 
                  Compare for equality with  | 
| 
                   | Advance by one position | 
| 
                   | Retreat by one position | 
| 
                   | 
                  Advance by  | 
| 
                   | 
                  Measure the distance to  | 
        In addition to implementing the core interface functions, an iterator derived
        from iterator_facade typically
        defines several constructors. To model any of the standard iterator concepts,
        the iterator must at least have a copy constructor. Also, if the iterator
        type X is meant to be automatically
        interoperate with another iterator type Y
        (as with constant and mutable iterators) then there must be an implicit conversion
        from X to Y
        or from Y to X (but not both), typically implemented
        as a conversion constructor. Finally, if the iterator is to model Forward
        Traversal Iterator or a more-refined iterator concept, a default constructor
        is required.
      
        iterator_facade and the operator
        implementations need to be able to access the core member functions in the
        derived class. Making the core member functions public would expose an implementation
        detail to the user. The design used here ensures that implementation details
        do not appear in the public interface of the derived iterator type.
      
        Preventing direct access to the core member functions has two advantages.
        First, there is no possibility for the user to accidently use a member function
        of the iterator when a member of the value_type was intended. This has been
        an issue with smart pointer implementations in the past. The second and main
        advantage is that library implementers can freely exchange a hand-rolled
        iterator implementation for one based on iterator_facade
        without fear of breaking code that was accessing the public core member functions
        directly.
      
        In a naive implementation, keeping the derived class' core member functions
        private would require it to grant friendship to iterator_facade
        and each of the seven operators. In order to reduce the burden of limiting
        access, iterator_core_access
        is provided, a class that acts as a gateway to the core member functions
        in the derived iterator class. The author of the derived class only needs
        to grant friendship to iterator_core_access
        to make his core member functions available to the library.
      
        iterator_core_access will
        be typically implemented as an empty class containing only private static
        member functions which invoke the iterator core member functions. There is,
        however, no need to standardize the gateway protocol. Note that even if
        iterator_core_access used
        public member functions it would not open a safety loophole, as every core
        member function preserves the invariants of the iterator.
      
operator\[\]
      
        The indexing operator for a generalized iterator presents special challenges.
        A random access iterator's operator[] is only required to return something convertible
        to its value_type. Requiring
        that it return an lvalue would rule out currently-legal random-access iterators
        which hold the referenced value in a data member (e.g. |counting|_), because
        *(p+n)
        is a reference into the temporary iterator p+n, which
        is destroyed when operator[]
        returns.
      
        .. |counting| replace:: counting_iterator
      
        Writable iterators built with iterator_facade
        implement the semantics required by the preferred resolution to issue 299_
        and adopted by proposal n1550_: the result of p[n]
        is an object convertible to the iterator's value_type,
        and p[n] =
        x is equivalent to *(p +
        n) = x (Note:
        This result object may be implemented as a proxy containing a copy of p+n).
        This approach will work properly for any random-access iterator regardless
        of the other details of its implementation. A user who knows more about the
        implementation of her iterator is free to implement an operator[] that returns an lvalue in the derived iterator
        class; it will hide the one supplied by iterator_facade
        from clients of her iterator.
      
.. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm
        .. _issue 299:
        http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299
      
        .. _operator arrow:
      
operator->
      
        The reference type of a readable
        iterator (and today's input iterator) need not in fact be a reference, so
        long as it is convertible to the iterator's value_type.
        When the value_type is a
        class, however, it must still be possible to access members through operator->.
        Therefore, an iterator whose reference
        type is not in fact a reference must return a proxy containing a copy of
        the referenced value from its operator->.
      
        The return types for iterator_facade's
        operator->
        and operator[]
        are not explicitly specified. Instead, those types are described in terms
        of a set of requirements, which must be satisfied by the iterator_facade
        implementation.
      
.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template Patterns, C++ Report, February 1995, pp. 24-27.
template < class Derived , class Value , class CategoryOrTraversal , class Reference = Value& , class Difference = ptrdiff_t > class iterator_facade { public: typedef remove_const<Value>::type value_type; typedef Reference reference; typedef Value\* pointer; typedef Difference difference_type; typedef /* see below__ \*/ iterator_category; reference operator\*() const; /* see below__ \*/ operator->() const; /* see below__ \*/ operator[](difference_type n) const; Derived& operator++(); Derived operator++(int); Derived& operator--(); Derived operator--(int); Derived& operator+=(difference_type n); Derived& operator-=(difference_type n); Derived operator-(difference_type n) const; protected: typedef iterator_facade iterator_facade\_; }; // Comparison operators template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); // Iterator difference template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> /* see below__ \*/ operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs); // Iterator addition template <class Dr, class V, class TC, class R, class D> Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&, typename Derived::difference_type n); template <class Dr, class V, class TC, class R, class D> Derived operator+ (typename Derived::difference_type n, iterator_facade<Dr,V,TC,R,D> const&);
          __ iterator category_
        
          __ operator arrow_
        
__ brackets_
__ minus_
          .. _iterator category:
        
          The iterator_category member
          of iterator_facade is
        
.. parsed-literal::
*iterator-category*\ (CategoryOrTraversal, value_type, reference)
where iterator-category is defined as follows:
.. include:: facade_iterator_category.rst
          The enable_if_interoperable
          template used above is for exposition purposes. The member operators should
          only be in an overload set provided the derived types Dr1
          and Dr2 are interoperable,
          meaning that at least one of the types is convertible to the other. The
          enable_if_interoperable
          approach uses SFINAE to take the operators out of the overload set when
          the types are not interoperable. The operators should behave as-if enable_if_interoperable
          were defined to be:
        
template <bool, typename> enable_if_interoperable_impl {}; template <typename T> enable_if_interoperable_impl<true,T> { typedef T type; }; template<typename Dr1, typename Dr2, typename T> struct enable_if_interoperable : enable_if_interoperable_impl< is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value , T > {};
          The following table describes the typical valid expressions on iterator_facade's Derived
          parameter, depending on the iterator concept(s) it will model. The operations
          in the first column must be made accessible to member functions of class
          iterator_core_access. In
          addition, static_cast<Derived*>(iterator_facade*)
          shall be well-formed.
        
          In the table below, F is
          iterator_facade<X,V,C,R,D>, a
          is an object of type X,
          b and c
          are objects of type const X, n
          is an object of F::difference_type, y
          is a constant object of a single pass iterator type interoperable with
          X, and z
          is a constant object of a random access traversal iterator type interoperable
          with X.
        
          .. _core operations:
        
          .. topic:: iterator_facade
          Core Operations
        
Table 1.11. Core Operations
| Expression | Return Type | Assertion/Note | Used to implement Iterator Concept(s) | 
|---|---|---|---|
| 
                     | 
                     | Readable Iterator, Writable Iterator | |
| 
                     | convertible to bool | 
                    true iff  | Single Pass Iterator | 
| 
                     | unused | Incrementable Iterator | |
| 
                     | unused | Bidirectional Traversal Iterator | |
| 
                     | unused | Random Access Traversal Iterator | |
| 
                     | 
                    convertible to  | 
                    equivalent to  | Random Access Traversal Iterator | 
          The operations in this section are described in terms of operations on
          the core interface of Derived
          which may be inaccessible (i.e. private). The implementation should access
          these operations through member functions of class iterator_core_access.
        
reference operator*() const;
          Returns: static_cast<Derived
          const*>(this)->dereference()
        
operator->() const; (see below__)
          __ operator arrow_
        
          Returns: If reference
          is a reference type, an object of type pointer
          equal to: &static_cast<Derived
          const*>(this)->dereference()
          Otherwise returns an object of unspecified type such that, (*static_cast<Derived
          const*>(this))->m is equivalent to (w = **static_cast<Derived
          const*>(this), w.m) for some temporary object w of type value_type.
        
.. _brackets:
*unspecified* operator[](difference_type n) const;
          Returns: an object convertible to value_type. For constant objects v of type value_type,
          and n of type difference_type, (*this)[n] = v
          is equivalent to *(*this
          + n) = v,
          and static_cast<value_type const&>((*this)[n])
          is equivalent to static_cast<value_type
          const&>(*(*this + n))
        
Derived& operator++();
Effects:
static_cast<Derived*>(this)->increment(); return *static_cast<Derived*>(this); Derived operator++(int);
Effects:
Derived tmp(static_cast<Derived const*>(this)); ++*this; return tmp; Derived& operator--();
Effects:
static_cast<Derived*>(this)->decrement(); return *static_cast<Derived*>(this); Derived operator--(int);
Effects:
Derived tmp(static_cast<Derived const*>(this)); --*this; return tmp; Derived& operator+=(difference_type n);
Effects:
static_cast<Derived*>(this)->advance(n); return *static_cast<Derived*>(this); Derived& operator-=(difference_type n);
Effects:
static_cast<Derived*>(this)->advance(-n); return *static_cast<Derived*>(this); Derived operator-(difference_type n) const;
Effects:
Derived tmp(static_cast<Derived const*>(this)); return tmp -= n; template <class Dr, class V, class TC, class R, class D> Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&, typename Derived::difference_type n); template <class Dr, class V, class TC, class R, class D> Derived operator+ (typename Derived::difference_type n, iterator_facade<Dr,V,TC,R,D> const&);
Effects:
Derived tmp(static_cast<Derived const*>(this)); return tmp += n; template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen((Dr1 const&)lhs).equal((Dr2 const&)rhs). Otherwise,((Dr2 const&)rhs).equal((Dr1 const&)lhs).
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen!((Dr1 const&)lhs).equal((Dr2 const&)rhs). Otherwise,!((Dr2 const&)rhs).equal((Dr1 const&)lhs).
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0. Otherwise,((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0.
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0. Otherwise,((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0.
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0. Otherwise,((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0.
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,bool>::type operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Returns:
ifis_convertible<Dr2,Dr1>::valuethen((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0. Otherwise,((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0.
.. _minus:
template <class Dr1, class V1, class TC1, class R1, class D1, class Dr2, class V2, class TC2, class R2, class D2> typename enable_if_interoperable<Dr1,Dr2,difference>::type operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs, iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
Return Type:
ifis_convertible<Dr2,Dr1>::valuethendifferenceshall beiterator_traits<Dr1>::difference_type. Otherwisedifferenceshall beiterator_traits<Dr2>::difference_type
Returns:
ifis_convertible<Dr2,Dr1>::valuethen-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs). Otherwise,((Dr2 const&)rhs).distance_to((Dr1 const&)lhs).
          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.
        
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.
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<...> { ... };
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
          _.
        
          .. 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_iterators
          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 > { ... };
          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 _. 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; };
          .. 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.
        
          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 this program.
        
__ ../example/node_iterator1.cpp
node_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; };
          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;
          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 _
          _:
        
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
          .. If you're using an older compiler and it can't
          handle this example, see the example
          code__ for workarounds.
        
          .. 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.
        
          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
        
          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