diff --git a/doc/counting_iterator.html b/doc/counting_iterator.html index 6f9e8b4..cc6303d 100644 --- a/doc/counting_iterator.html +++ b/doc/counting_iterator.html @@ -3,13 +3,240 @@ - + Counting Iterator - +
@@ -208,5 +435,11 @@ indirectly printing out the numbers from 0 to 7
+ + diff --git a/doc/default.css b/doc/default.css index 2e1fddb..0e4226a 100644 --- a/doc/default.css +++ b/doc/default.css @@ -29,7 +29,7 @@ div.abstract p.topic-title { text-align: center } div.attention, div.caution, div.danger, div.error, div.hint, -div.important, div.note, div.tip, div.warning { +div.important, div.note, div.tip, div.warning, div.admonition { margin: 2em ; border: medium outset ; padding: 1em } @@ -42,7 +42,8 @@ div.warning p.admonition-title { font-family: sans-serif } div.hint p.admonition-title, div.important p.admonition-title, -div.note p.admonition-title, div.tip p.admonition-title { +div.note p.admonition-title, div.tip p.admonition-title, +div.admonition p.admonition-title { font-weight: bold ; font-family: sans-serif } @@ -61,6 +62,19 @@ div.figure { div.footer, div.header { font-size: smaller } +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 0em 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + div.system-messages { margin: 5em } @@ -105,6 +119,10 @@ ol.lowerroman { ol.upperroman { list-style: upper-roman } +p.attribution { + text-align: right ; + margin-left: 50% } + p.caption { font-style: italic } @@ -115,6 +133,21 @@ p.credits { p.label { white-space: nowrap } +p.rubric { + font-weight: bold ; + font-size: larger ; + color: maroon ; + text-align: center } + +p.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + p.topic-title { font-weight: bold } @@ -144,6 +177,9 @@ span.classifier-delimiter { span.interpreted { font-family: sans-serif } +span.option { + white-space: nowrap } + span.option-argument { font-style: italic } diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html index 0e52f59..7db6b6b 100755 --- a/doc/facade-and-adaptor.html +++ b/doc/facade-and-adaptor.html @@ -3,12 +3,239 @@ - + Iterator Facade and Adaptor - +
@@ -76,62 +303,68 @@ by adapting other iterators.
  • Header <iterator_helper> synopsis [lib.iterator.helper.synopsis]
  • Iterator facade [lib.iterator.facade]
  • -
  • Iterator adaptor [lib.iterator.adaptor]
  • -

    iterator_facade iterator category

    +

    iterator_facade iterator category

    The iterator_category member of iterator_facade<X,V,R,C,D> is a type which satisfies the following conditions:

    @@ -842,7 +1072,7 @@ convertible, and not to any more-derived traversal tag type.

    -

    iterator_facade operations

    +

    iterator_facade operations

    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 @@ -985,7 +1215,7 @@ return tmp -= n;

    -

    Iterator adaptor [lib.iterator.adaptor]

    +

    Iterator adaptor [lib.iterator.adaptor]

    -

    Class template indirect_iterator

    +

    Class template indirect_iterator

     template <
         class Iterator
    @@ -1319,7 +1549,7 @@ satisfies the requirements of the concepts modeled by the indirect
     iterator as specified in the models section.

    -

    indirect_iterator requirements

    +

    indirect_iterator requirements

    The Iterator argument shall meet the requirements of Readable Iterator. The CategoryOrTraversal argument shall be one of the standard iterator tags or use_default. If CategoryOrTraversal @@ -1335,7 +1565,7 @@ is not use_default, as implied default for the value_type member.

    -

    indirect_iterator models

    +

    indirect_iterator models

    If CategoryOrTraversal is a standard iterator tag, indirect_iterator is a model of the iterator concept corresponding to the tag, otherwise indirect_iterator satisfies the requirements @@ -1349,7 +1579,7 @@ the Iterator argument.

    indirect_iterator models Lvalue Iterator.

    -

    indirect_iterator operations

    +

    indirect_iterator operations

    indirect_iterator();

    @@ -1398,19 +1628,17 @@ indirect_iterator(
    -

    Reverse iterator

    +

    Reverse iterator

    The reverse iterator adaptor flips the direction of a base iterator's motion. Invoking operator++() moves the base iterator backward and invoking operator--() moves the base iterator forward.

    -

    Class template reverse_iterator

    +

    Class template reverse_iterator

     template <class Iterator>
    -class reverse_iterator :
    -  public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
    +class reverse_iterator
     {
    -  friend class iterator_core_access;
     public:
       reverse_iterator() {}
       explicit reverse_iterator(Iterator x) ;
    @@ -1420,34 +1648,28 @@ public:
           reverse_iterator<OtherIterator> const& r
         , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
       );
    -
    -private: // as-if specification
    -  typename reverse_iterator::reference dereference() const { return *prior(this->base()); }
    -
    -  void increment() { --this->base_reference(); }
    -  void decrement() { ++this->base_reference(); }
    -
    -  void advance(typename reverse_iterator::difference_type n)
    -  {
    -      this->base_reference() += -n;
    -  }
    -
    -  template <class OtherIterator>
    -  typename reverse_iterator::difference_type
    -  distance_to(reverse_iterator<OtherIterator> const& y) const
    -  {
    -      return this->base_reference() - y.base();
    -  }
    -
    +  reference operator*() const;
    +  reverse_iterator& operator++();
    +private:
    +  Iterator current; // exposition
     };
     
    +
    -

    reverse_iterator requirements

    +

    reverse_iterator requirements

    The base Iterator must be a model of Bidirectional Traversal -Iterator. The resulting reverse_iterator will be a model of the -most refined standard traversal and access concepts that are modeled -by Iterator.

    +Iterator and Readable Iterator.

    +
    +
    +

    reverse_iterator models

    +

    reverse_iterator models Bidirectional Traversal Iterator and +Readable Iterator. In addition, reverse_iterator models the same +standard iterator access concepts that the Iterator +argument models.

    +
    +
    +

    reverse_iterator operations

    reverse_iterator();

    @@ -1455,8 +1677,8 @@ by Iterator.

    - +
    Requires:Iterator must be Default Constructible.
    Returns:An instance of reverse_iterator with a -default constructed base object.
    Returns:An instance of reverse_iterator with current +default constructed.
    @@ -1466,7 +1688,7 @@ default constructed base object. Returns:An instance of reverse_iterator with a -base object copy constructed from x. +current constructed from x. @@ -1487,17 +1709,40 @@ reverse_iterator( -
    +

    reference operator*() const;

    + +++ + + + +
    Effects:
    +
    +Iterator tmp = current;
    +return *--tmp;
    +
    +

    reverse_iterator& operator++();

    + +++ + + + + + +
    Effects:--current
    Returns:*this
    -

    Transform iterator

    +

    Transform iterator

    The transform iterator adapts an iterator by applying some function object to the result of dereferencing the iterator. In other words, the operator* of the transform iterator first dereferences the base iterator, passes the result of this to the function object, and then returns the result.

    -

    Class template transform_iterator

    +

    Class template transform_iterator

     template <class UnaryFunction,
    @@ -1505,9 +1750,7 @@ template <class UnaryFunction,
               class Reference = use_default, 
               class Value = use_default>
     class transform_iterator
    -  : public iterator_adaptor</* see discussion */>
     {
    -  friend class iterator_core_access;
     public:
       transform_iterator();
       transform_iterator(Iterator const& x, UnaryFunction f);
    @@ -1519,22 +1762,29 @@ public:
           , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition
       );
     
    +  reference operator*() const;
    +  transform_iterator& operator++();
    +  Iterator base() const;
       UnaryFunction functor() const;
     private:
    -  typename transform_iterator::value_type dereference() const;
    -  UnaryFunction m_f;
    +  Iterator m_iterator; // exposition
    +  UnaryFunction m_f;   // exposition
     };
     
    +
    -

    transform_iterator requirements

    +

    transform_iterator requirements

    The type UnaryFunction must be Assignable, Copy Constructible, and the expression f(*i) must be valid where f is an object of type UnaryFunction, i is an object of type Iterator, and where the type of f(*i) must be result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type.

    -

    The type Iterator must at least model Readable Iterator. The -resulting transform_iterator models the most refined of the +

    The type Iterator must at least model Readable Iterator.

    +
    +
    +

    transform_iterator models

    +

    The resulting transform_iterator models the most refined of the following options that is also modeled by Iterator.

    -
    -

    transform_iterator public operations

    +
    +

    transform_iterator operations

    transform_iterator();

    @@ -1589,6 +1839,15 @@ transform_iterator(
    +

    Iterator base() const;

    + +++ + + + +
    Returns:m_iterator

    UnaryFunction functor() const;

    @@ -1598,22 +1857,29 @@ transform_iterator(
    -
    -
    -

    transform_iterator private operations

    -

    typename transform_iterator::value_type dereference() const;

    +

    reference operator*() const;

    - + + + +
    Returns:m_f(transform_iterator::dereference());
    Returns:m_f(*m_iterator)
    +

    transform_iterator& operator++();

    + +++ + + +
    Effects:++m_iterator
    Returns:*this
    -
    -

    Filter iterator

    +

    Filter iterator

    The filter iterator adaptor creates a view of an iterator range in which some elements of the range are skipped over. A predicate function object controls which elements are skipped. When the @@ -1625,7 +1891,7 @@ of the underlying range. Therefore the constructor of the filter iterator takes two iterator parameters: the position for the filtered iterator and the end of the range.

    -

    Class template filter_iterator

    +

    Class template filter_iterator

     template <class Predicate, class Iterator>
     class filter_iterator
    @@ -1647,15 +1913,17 @@ class filter_iterator
             );
         Predicate predicate() const;
         Iterator end() const;
    +    reference operator*() const;
    +    filter_iterator& operator++();
     };
     
    -

    The iterator_category is a type convertible to the tags +

    The iterator_category member is a type convertible to the tags corresponding to each standard concept modeled by filter_iterator, as described in the models section.

    -

    filter_iterator requirements

    +

    filter_iterator requirements

    The Predicate argument must be Assignable, Copy Constructible, and the expression p(x) must be valid where p is an object of type Predicate, x is an object of type @@ -1666,7 +1934,7 @@ Iterator and Single Pass Iterator or it shall meet the requirements of Input Iterator.

    -

    filter_iterator models

    +

    filter_iterator models

    The concepts that filter_iterator models are dependent on what concepts the Iterator argument models, as specified in the following tables.

    @@ -1733,33 +2001,9 @@ following tables.

    - ---- - - - - - - - - - - - - - - - - -
    If Iterator modelsthen filter_iterator models
    Input IteratorInput Iterator, Readable Iterator, Single Pass Iterator
    Forward IteratorForward Iterator, Readable Lvalue Iterator, -Forward Traversal Iterator
    Mutable Forward IteratorMutable Forward Iterator, Writable Lvalue Iterator, -Forward Traversal Iterator
    -

    filter_iterator operations

    +

    filter_iterator operations

    In addition to those operations required by the concepts that filter_iterator models, filter_iterator provides the following operations.

    @@ -1781,8 +2025,8 @@ whose end is a default constru -Returns:A filter_iterator at position x that filters according -to predicate f and that will not increment past end. +Returns:A filter_iterator at the first position in the range [x,end) +such that f(*this->base()) == true or else at position end. @@ -1793,6 +2037,10 @@ to predicate f and that will n Requires:Predicate must be Default Constructible. +Returns:A filter_iterator at the first position in the range [x,end) +such that f(*this->base()) == true, where f is a default +constructed Predicate, or else at position end. + Returns:A filter_iterator at position x that filters according to a default constructed Predicate and that will not increment past end. @@ -1812,7 +2060,8 @@ filter_iterator( Requires:OtherIterator is implicitly convertible to Iterator. -Returns:A copy of iterator t. +Returns:A filter iterator at the same position as iterator t +whose predicate and end are copies of t.predicate and t.end() . @@ -1834,43 +2083,50 @@ filter_iterator( +

    reference operator*() const;

    + +++ + + + +
    Returns:*(this->base())
    +

    filter_iterator& operator++();

    + +++ + + + + + +
    Effects:Increments *this and then continues to +increment *this until either this->base() == this->end() +or f(**this) == true.
    Returns:*this
    -

    Counting iterator

    -

    The counting iterator adaptor implements dereference by returning a -reference to the base object. The other operations are implemented by -the base m_iterator, as per the inheritance from -iterator_adaptor.

    +

    Counting iterator

    +

    counting_iterator adapts an arithmetic type, such as int, by +adding an operator* that returns the current value of the object.

    -

    Class template counting_iterator

    +

    Class template counting_iterator

     template <
         class Incrementable
    -  , unsigned Access = use_default_access
    -  , class Traversal = use_default
    +  , class CategoryOrTraversal = use_default
       , class Difference = use_default
     >
     class counting_iterator
    -  : public iterator_adaptor<
    -        counting_iterator<Incrementable, Access, Traversal, Difference>
    -      , Incrementable
    -      , Incrementable
    -      , Access
    -      , /* see details for traversal category */
    -      , Incrementable const&
    -      , Incrementable const*
    -      , /* distance = Difference or a signed integral type */>
     {
    -    friend class iterator_core_access;
      public:
         counting_iterator();
         counting_iterator(counting_iterator const& rhs);
    -    counting_iterator(Incrementable x);
    +    explicit counting_iterator(Incrementable x);
    +    Incrementable base() const;
      private:
    -    typename counting_iterator::reference dereference() const
    -    {
    -        return this->base_reference();
    -    }
    +    Incrementable current; // exposition
       };
     
    @@ -1881,11 +2137,14 @@ the cases when the Incrementable
    -

    counting_iterator requirements

    +

    counting_iterator requirements

    The Incrementable type must be Default Constructible, Copy Constructible, and Assignable. The default distance is -an implementation defined signed integegral type.

    -

    The resulting counting_iterator models Readable Lvalue Iterator.

    +an implementation defined signed integral type.

    +
    +
    +

    counting_iterator models

    +

    counting_iterator models Readable Lvalue Iterator.

    Furthermore, if you wish to create a counting iterator that is a Forward Traversal Iterator, then the following expressions must be valid:

    @@ -1909,7 +2168,7 @@ i < j
     
    -

    counting_iterator operations

    +

    counting_iterator operations

    counting_iterator();

    @@ -1928,19 +2187,46 @@ i < j
    -

    counting_iterator(Incrementable x);

    +

    explicit counting_iterator(Incrementable x);

    - + + + +
    Returns:An instance of counting_iterator with its base -object copy constructed from x.
    Returns:An instance of counting_iterator with current +constructed from x.
    +

    reference operator*() const;

    + +++ + + + +
    Returns:current
    +

    counting_iterator& operator++();

    + +++ + + + +
    Effects:++current
    +

    Incrementable base() const;

    + +++ +
    Returns:current
    -

    Function output iterator

    +

    Function output iterator

    The function output iterator adaptor makes it easier to create custom output iterators. The adaptor takes a unary function and creates a model of Output Iterator. Each item assigned to the output iterator is @@ -1949,7 +2235,7 @@ iterator is that creating a conforming output iterator is non-trivial, particularly because the proper implementation usually requires a proxy object.

    -

    Class template function_output_iterator

    +

    Class template function_output_iterator

     template <class UnaryFunction>
     class function_output_iterator {
    @@ -1977,7 +2263,7 @@ public:
     
    -

    function_output_iterator requirements

    +

    function_output_iterator requirements

    The UnaryFunction must be Assignable, Copy Constructible, and the expression f(x) must be valid, where f is an object of type UnaryFunction and x is an object of a type accepted by f. @@ -1985,7 +2271,7 @@ The resulting function_output_iterator

    -

    function_output_iterator operations

    +

    function_output_iterator operations

    explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

    @@ -2026,7 +2312,7 @@ a copy of the unary function f
    -

    function_output_iterator::output_proxy operations

    +

    function_output_iterator::output_proxy operations

    output_proxy(UnaryFunction& f);

    @@ -2060,5 +2346,11 @@ LocalWords: OtherIncrementable Coplien --> + + diff --git a/doc/filter_iterator.html b/doc/filter_iterator.html index 4ca83ec..47f0f6d 100644 --- a/doc/filter_iterator.html +++ b/doc/filter_iterator.html @@ -3,13 +3,240 @@ - +Filter Iterator - + - +
    @@ -27,7 +254,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction
    - + @@ -266,6 +493,8 @@ whose predicate and end are copies of t.pr increment *this until either this->base() == this->end() or f(**this) == true. + +
    Date:2004-01-11
    2004-01-12
    Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
    Returns:*this
    @@ -362,5 +591,11 @@ int main()
     
    + + diff --git a/doc/function_output_iterator.html b/doc/function_output_iterator.html index 33451c9..d1fedc3 100644 --- a/doc/function_output_iterator.html +++ b/doc/function_output_iterator.html @@ -3,13 +3,240 @@ - + Function Output Iterator - +
    @@ -155,5 +382,11 @@ return *this;
    + + diff --git a/doc/index.html b/doc/index.html index 6fa7d71..5dcbe19 100755 --- a/doc/index.html +++ b/doc/index.html @@ -3,9 +3,236 @@ - + The Boost.Iterator Library Boost - + + + diff --git a/doc/indirect_iterator.html b/doc/indirect_iterator.html index f95ceb4..5dc64c1 100644 --- a/doc/indirect_iterator.html +++ b/doc/indirect_iterator.html @@ -3,13 +3,240 @@ - + Indirect Iterator - +
    @@ -196,5 +423,11 @@ indirect_iterator(
    + + diff --git a/doc/iterator_adaptor.html b/doc/iterator_adaptor.html index ece40fa..2914c61 100644 --- a/doc/iterator_adaptor.html +++ b/doc/iterator_adaptor.html @@ -3,13 +3,240 @@ - + Iterator Adaptor - +
    @@ -324,5 +551,11 @@ typename iterator_adaptor::difference_type distance_to(
    + + diff --git a/doc/iterator_facade.html b/doc/iterator_facade.html index ea09999..d256715 100644 --- a/doc/iterator_facade.html +++ b/doc/iterator_facade.html @@ -3,13 +3,240 @@ - + Iterator Facade - +
    @@ -45,24 +272,44 @@ and associated types, to be supplied by a derived iterator class.
    -

    Overview

    +

    Overview

    -

    Motivation

    +

    Motivation

    -

    Introduction

    +

    Introduction

    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.

    -

    The Problem

    -

    Say we've written a polymorphic linked list node as follows:

    +

    The Problem

    +

    Say we've written a polymorphic linked list node base class:

     # include <iostream>
     
    @@ -279,22 +526,24 @@ 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 twice() = 0;
    +    virtual void double_me() = 0;
     
         void append(node_base* p)
         {
    -        if (m_next)
    -            m_next->append(p);
    +        if (m_next) 
    +            m_next->append(p); 
             else
    -            m_next = p;
    +            m_next = p; 
         }
     
      private:
    @@ -312,7 +561,7 @@ struct node : node_base
         {}
     
         void print(std::ostream& s) const { s << this->m_value; }
    -    void twice() { m_value += m_value; }
    +    void double_me() { m_value += m_value; }
     
      private:
         T m_value;
    @@ -326,16 +575,398 @@ inline std::ostream& operator<<(std::ostream& s, node_base const&a
         return s;
     }
     
    - +
    +

    A Basic Iterator Using iterator_facade

    +
    +

    Template Parameters

    +

    The first step in building a concrete iterator with iterator_facade +is to decide what its template parameters will be.

    +
    +

    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 1.

    + + + + + +
    [1]iterator_facade also supports old-style category +tags, so we could've passed std::forward_iterator_tag here; +either way, the resulting iterator's iterator_category will +end up being std::forward_iterator_tag.
    -

    Reference

    +

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

    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 2. +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;
    +};
    +
    + + + + + +
    [2]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.
    +
    +
    +

    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.

    +

    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Ć ; a complete and conforming readable, forward-traversal +iterator! For a working example of its use, see this program.

    +
    +
    +
    +

    A constant 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;
    +
    +
    +
    +

    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 3 4:

    +
    +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;
    +
    + + + + + +
    [3]If you're using an older compiler and it can't handle +this example, see the example code for workarounds.
    + + + + + +
    [4]If node_iterator had been a random access +traversal iterator, we'd have had to templatize its +distance_to function as well.
    +

    You can see an example program which exercises our interoperable +iterators here.

    +
    +
    +

    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.

    +

    In fact, that sort of magic is possible using +boost::enable_if. By rewriting the converting constructor as +follows, we can remove it from the overload set when it's not +appropriate:

    +
    +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) {}
    +
    +
    +
    +

    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.

    +
    +
    +
    +

    Reference

    -

    Ref

    +

    Ref

    We need to resolve the title levels here.

    @@ -448,7 +1079,7 @@ struct enable_if_interoperable {};
    -

    iterator_facade usage

    +

    iterator_facade usage

    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 @@ -460,6 +1091,8 @@ object of type X, X, and z is a constant object of a random access traversal iterator type interoperable with X.

    +
    +

    iterator_facade Core Operations

    @@ -482,12 +1115,6 @@ Concept(s) - - - - - - - - - - @@ -512,6 +1133,12 @@ Iterator + + + + + @@ -531,8 +1158,9 @@ Iterator
    Readable Iterator, Writable Iterator
    c.equal(b)convertible to booltrue iff b and c are -equivalent.Single Pass Iterator
    c.equal(y) convertible to bool true iff c and y refer to the @@ -495,12 +1122,6 @@ same position. Implements c c != y. Single Pass Iterator
    a.advance(n)unused Random Access Traversal -Iterator
    a.increment() unused   Bidirectional Traversal Iterator
    a.advance(n)unused Random Access Traversal +Iterator
    c.distance_to(b) convertible to F::difference_type
    +
    -

    iterator_facade iterator category

    +

    iterator_facade iterator category

    The iterator_category member of iterator_facade<X,V,R,C,D> is a type which satisfies the following conditions:

    @@ -585,7 +1213,7 @@ convertible, and not to any more-derived traversal tag type.

    -

    iterator_facade operations

    +

    iterator_facade operations

    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 @@ -728,5 +1356,11 @@ return tmp -= n;

    + + diff --git a/doc/iterator_facade_ref.rst b/doc/iterator_facade_ref.rst index c763573..54efe9d 100644 --- a/doc/iterator_facade_ref.rst +++ b/doc/iterator_facade_ref.rst @@ -136,6 +136,11 @@ 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`: + +``iterator_facade`` Core Operations +''''''''''''''''''''''''''''''''''' + +--------------------+----------------------+-------------------------------------+---------------------------+ |Expression |Return Type |Assertion/Note |Used to implement Iterator | | | | |Concept(s) | @@ -143,21 +148,18 @@ interoperable with ``X``. |``c.dereference()`` |``F::reference`` | |Readable Iterator, Writable| | | | |Iterator | +--------------------+----------------------+-------------------------------------+---------------------------+ -|``c.equal(b)`` |convertible to bool |true iff ``b`` and ``c`` are |Single Pass Iterator | -| | |equivalent. | | -+--------------------+----------------------+-------------------------------------+---------------------------+ |``c.equal(y)`` |convertible to bool |true iff ``c`` and ``y`` refer to the|Single Pass Iterator | | | |same position. Implements ``c == y``| | | | |and ``c != y``. | | +--------------------+----------------------+-------------------------------------+---------------------------+ -|``a.advance(n)`` |unused | |Random Access Traversal | -| | | |Iterator | -+--------------------+----------------------+-------------------------------------+---------------------------+ |``a.increment()`` |unused | |Incrementable Iterator | +--------------------+----------------------+-------------------------------------+---------------------------+ |``a.decrement()`` |unused | |Bidirectional Traversal | | | | |Iterator | +--------------------+----------------------+-------------------------------------+---------------------------+ +|``a.advance(n)`` |unused | |Random Access Traversal | +| | | |Iterator | ++--------------------+----------------------+-------------------------------------+---------------------------+ |``c.distance_to(b)``|convertible to |equivalent to ``distance(c, b)`` |Random Access Traversal | | |``F::difference_type``| |Iterator | +--------------------+----------------------+-------------------------------------+---------------------------+ diff --git a/doc/iterator_facade_tutorial.rst b/doc/iterator_facade_tutorial.rst index 3437bef..553b7cb 100755 --- a/doc/iterator_facade_tutorial.rst +++ b/doc/iterator_facade_tutorial.rst @@ -12,7 +12,7 @@ example of a linked list of polymorphic objects. The Problem ----------- -Say we've written a polymorphic linked list node as follows:: +Say we've written a polymorphic linked list node base class:: # include @@ -20,22 +20,24 @@ Say we've written a polymorphic linked list node as follows:: { 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 twice() = 0; + virtual void double_me() = 0; void append(node_base* p) { - if (m_next) - m_next->append(p); + if (m_next) + m_next->append(p); else - m_next = p; + m_next = p; } private: @@ -53,7 +55,7 @@ specializations of the following template:: {} void print(std::ostream& s) const { s << this->m_value; } - void twice() { m_value += m_value; } + void double_me() { m_value += m_value; } private: T m_value; @@ -67,7 +69,422 @@ And we can print any node using the following streaming operator:: return s; } +Our first challenge is to build an appropriate iterator over these +lists. -.. sidebar:: Note +A Basic Iterator Using ``iterator_facade`` +------------------------------------------ + +Template Parameters +................... + +The first step in building a concrete iterator with iterator_facade +is to decide what its template parameters will be. + +``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've 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::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::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 + + 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 + + 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. + +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 + + 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ą; 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 node_iter + : public boost::iterator_facade< + node_iter + , 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 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_iterator; + typedef node_iter 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``\ '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 node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter(node_iter const& other) + : m_node(other.m_node) {} + + private: + friend class boost::iterator_core_access; + template friend class node_iter; + + template + bool equal(node_iter 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_iterator; + typedef impl::node_iterator node_const_iterator; + +.. [#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|_\ ``::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:: + + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , 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 - This is in progress; check the ../example directory for code. \ No newline at end of file diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html index 8b40d3e..ec815a3 100755 --- a/doc/new-iter-concepts.html +++ b/doc/new-iter-concepts.html @@ -3,13 +3,240 @@ - + New Iterator Concepts - +
    @@ -881,5 +1108,11 @@ LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct LocalWords: TraversalTag typename lvalues DWA Hmm JGS mis enum -->
    + + diff --git a/doc/permutation_iterator.html b/doc/permutation_iterator.html index d0e76a2..5852cd5 100644 --- a/doc/permutation_iterator.html +++ b/doc/permutation_iterator.html @@ -3,13 +3,240 @@ - + Permutation Iterator - +
    @@ -119,5 +346,11 @@ ForwardIterator instead of amortized constant time.

    + + diff --git a/doc/reverse_iterator.html b/doc/reverse_iterator.html index 95f1b9f..46a933c 100644 --- a/doc/reverse_iterator.html +++ b/doc/reverse_iterator.html @@ -3,13 +3,240 @@ - + Reverse Iterator - + - +
    @@ -27,7 +254,7 @@ Lab, University of Hanover Institute for Transport Railway Operation and Construction Date: -2004-01-11 +2004-01-12 Copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved @@ -202,5 +429,11 @@ sequence in double-reversed (normal) order: hello world!
    + + diff --git a/example/Jamfile b/example/Jamfile index fce5509..9ca17af 100644 --- a/example/Jamfile +++ b/example/Jamfile @@ -2,6 +2,9 @@ subproject libs/iterator/example ; import testing ; +# Make tests run by default. +DEPENDS all : test ; + test-suite iterator_examples : [ run reverse_iterator.cpp ] [ run node_iterator1.cpp ] diff --git a/example/node.hpp b/example/node.hpp index b9e482c..4e80d96 100755 --- a/example/node.hpp +++ b/example/node.hpp @@ -23,7 +23,7 @@ struct node_base } virtual void print(std::ostream& s) const = 0; - virtual void twice() = 0; + virtual void double_me() = 0; void append(node_base* p) { @@ -51,7 +51,7 @@ struct node : node_base {} void print(std::ostream& s) const { s << this->m_value; } - void twice() { m_value += m_value; } + void double_me() { m_value += m_value; } private: T m_value; diff --git a/example/node_iterator1.cpp b/example/node_iterator1.cpp index 2b3ac00..6411b03 100755 --- a/example/node_iterator1.cpp +++ b/example/node_iterator1.cpp @@ -23,7 +23,7 @@ int main() std::for_each( node_iterator(nodes.get()), node_iterator() - , std::mem_fun_ref(&node_base::twice) + , std::mem_fun_ref(&node_base::double_me) ); std::copy( diff --git a/example/node_iterator1.hpp b/example/node_iterator1.hpp index 281f30a..1188c7c 100755 --- a/example/node_iterator1.hpp +++ b/example/node_iterator1.hpp @@ -23,9 +23,9 @@ class node_iterator : m_node(p) {} + private: friend class boost::iterator_core_access; - private: void increment() { m_node = m_node->next(); } diff --git a/example/node_iterator2.cpp b/example/node_iterator2.cpp index 9985c6f..62211b2 100755 --- a/example/node_iterator2.cpp +++ b/example/node_iterator2.cpp @@ -31,7 +31,7 @@ int main() std::for_each( node_iterator(nodes.get()), node_iterator() - , boost::mem_fn(&node_base::twice) + , boost::mem_fn(&node_base::double_me) ); std::copy( diff --git a/example/node_iterator2.hpp b/example/node_iterator2.hpp index 194cf95..15b40aa 100755 --- a/example/node_iterator2.hpp +++ b/example/node_iterator2.hpp @@ -12,65 +12,62 @@ # include # endif -namespace impl +template +class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > { - template - class node_iterator - : public boost::iterator_facade< - node_iterator - , Value - , boost::forward_traversal_tag - > - { - private: - enum enabler {}; - - public: - node_iterator() - : m_node(0) - {} + private: + struct enabler {}; // a private type avoids misuse - explicit node_iterator(Value* p) - : m_node(p) - {} + public: + node_iter() + : m_node(0) {} - template - node_iterator( - node_iterator const& other + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter( + node_iter const& other # ifndef BOOST_NO_SFINAE - , typename boost::enable_if,enabler*>::type = 0 + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() # endif - ) - : m_node(other.m_node) - { - } - + ) + : m_node(other.m_node) {} + - friend class boost::iterator_core_access; # if !BOOST_WORKAROUND(__GNUC__, == 2) - private: // GCC2 can't even grant that friendship to template member functions + private: // GCC2 can't even grant that friendship to template member functions # endif - template - bool equal(node_iterator const& other) const - { return this->m_node == other.m_node; } - - public: - void increment() - { m_node = m_node->next(); } + friend class boost::iterator_core_access; - Value& dereference() const - { return *m_node; } + template + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + private: + void increment() { m_node = m_node->next(); } + + Value& dereference() const { return *m_node; } # ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - public: + public: # else - template friend class node_iterator; + template friend class node_iter; # endif - Value* m_node; - }; -} + Value* m_node; +}; -typedef impl::node_iterator node_iterator; -typedef impl::node_iterator node_const_iterator; +typedef node_iter node_iterator; +typedef node_iter node_const_iterator; #endif // NODE_ITERATOR2_DWA2004110_HPP