diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html index 465c920..270976f 100755 --- a/doc/facade-and-adaptor.html +++ b/doc/facade-and-adaptor.html @@ -3,11 +3,11 @@
- +Iterators play an important role in modern C++ programming. The iterator is the central abstraction of the algorithms of the Standard Library, allowing algorithms to be re-used in in a wide variety of @@ -222,15 +225,15 @@ applies some user-specified function during the dereference of the iterator.
This proposal is purely an addition to the C++ standard library. However, note that this proposal relies on the proposal for New Iterator Concepts.
This proposal is formulated in terms of the new iterator concepts as proposed in n1550, since user-defined and especially adapted iterators suffer from the well known categorization problems that are @@ -240,7 +243,7 @@ is a direct mapping between new and old categories. This proposal could be reformulated using this mapping if n1550 was not accepted.
The question of iterator interoperability is poorly addressed in the current standard. There are currently two defect reports that are concerned with interoperability issues.
@@ -260,7 +263,7 @@ fixes the issues raised in 280. It provides the desired interoperability without introducing unwanted overloads.The enable_if_interoperable template used above is for exposition -purposes. The member operators should be only be in an overload set +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 @@ -699,25 +759,29 @@ struct enable_if_interoperable > {}; -
+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.
+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.
-Expression | @@ -734,25 +798,13 @@ Concept(s)Readable Iterator, Writable Iterator | |||
---|---|---|---|---|
c.equal(b) | -convertible to bool | -true iff b and c are -equivalent. | -Single Pass Iterator | -|
c.equal(y) | convertible to bool | -true iff c and y refer to the -same position. Implements c == y -and c != y. | +true iff c and y +refer to the same +position. | Single Pass Iterator |
a.advance(n) | -unused | -- | Random Access Traversal -Iterator | -|
a.increment() | unused | @@ -764,80 +816,26 @@ Iterator | Bidirectional Traversal Iterator | |
c.distance_to(b) | -convertible to -F::difference_type | -equivalent to distance(c, b) | +||
a.advance(n) | +unused | +Random Access Traversal Iterator | ||
c.distance_to(z) | convertible to F::difference_type | -equivalent to distance(c, z). -Implements c - z, c < z, c -<= z, c > z, and c >= c. | +equivalent to +distance(c, X(z)). | Random Access Traversal Iterator |
The iterator_category member of iterator_facade<X,V,R,C,D> -is a type which satisfies the following conditions:
--+-
-- -
if C is convertible to std::input_iterator_tag or -C is convertible to std::output_iterator_tag, -iterator_category is the same as C.
-- -
Otherwise, if C is not convertible to -incrementable_traversal_tag, the program is ill-formed
-- -
Otherwise:
--
-- -
iterator_category is convertible to the iterator -category tag or tags given by the following algorithm, and -not to any more-derived iterator category tag or tags:
--if (R is a reference type - && C is convertible to forward_traversal_tag) -{ - if (C is convertible to random_access_traversal_tag) - return random_access_iterator_tag - else if (C is convertible to bidirectional_traversal_tag) - return bidirectional_iterator_tag - else - return forward_traversal_tag -} -else -{ - if (C is convertible to single_pass_traversal_tag - && R is convertible to V) - { - if (V is const) - return input_iterator_tag - else - return input_iterator_tag and output_iterator_tag - } - else - return output_iterator_tag -} --- -
iterator_traversal<X>::type is convertible to the most -derived traversal tag type to which C is also -convertible, and not to any more-derived traversal tag type.
-
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 @@ -873,10 +871,12 @@ of type pointer equal to:
static_cast<Derived*>(this)->decrement(); -return static_cast<Derived*>(this); +return *static_cast<Derived*>(this);
static_cast<Derived*>(this)->advance(n); -return static_cast<Derived*>(this); +return *static_cast<Derived*>(this);
static_cast<Derived*>(this)->advance(-n); -return static_cast<Derived*>(this); +return *static_cast<Derived*>(this);
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +
|
+
---|
+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: | if is_convertible<Dr2,Dr1>::value +++ |
+
---|---|
Returns: | if is_convertible<Dr2,Dr1>::value +
|
+
static_cast<Derived*>(iterator_adaptor*) shall be well-formed. +The Base argument shall be Assignable and Copy Constructible.
The V, C, R, and D parameters of the iterator_facade +
The V', C', R', and D' parameters of the iterator_facade used as a base class in the summary of iterator_adaptor above are defined as follows:
-V = if (Value is use_default) +V' = if (Value is use_default) return iterator_traits<Base>::value_type else return Value -C = if (CategoryOrTraversal is use_default) +C' = if (CategoryOrTraversal is use_default) return iterator_traversal<Base>::type else return CategoryOrTraversal -R = if (Reference is use_default) +R' = if (Reference is use_default) if (Value is use_default) return iterator_traits<Base>::reference else @@ -1065,26 +1256,25 @@ above are defined as follows: else return Reference -D = if (Difference is use_default) +D' = if (Difference is use_default) return iterator_traits<Base>::difference_type else return Difference-
The Derived template parameter must be a publicly derived from -iterator_adaptor. In order for Derived to model the -iterator concepts corresponding to -iterator_traits<Derived>::iterator_category, the expressions -involving m_iterator in the specifications of those private -member functions of iterator_adaptor that may be called by -iterator_facade<Derived, ``\ *V*\, \ *C*\, \ *R*\, \ -*D*\>`` in evaluating any valid expression involving Derived -in those concepts' requirements.
+ + +iterator_adaptor();
Base base() const;
+Base const& base() const;
Base const& base_reference() const;
typename iterator_adaptor::reference dereference() const;
Requires: | For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +Dereferenceable::element_type shall be an accessible type. +Otherwise iterator_traits<Dereferenceable>::value_type shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of pointee] | +
---|
type is determined according to the following algorithm, where +x is an object of type Dereferenceable:
++if ( ++x is ill-formed ) +{ + return ``Dereferenceable::element_type`` +} +else if (``*x`` is a mutable reference to + std::iterator_traits<Dereferenceable>::value_type) +{ + return iterator_traits<Dereferenceable>::value_type +} +else +{ + return iterator_traits<Dereferenceable>::value_type const +} ++
+template <class Dereferenceable> +struct indirect_reference +{ + typedef /* see below */ type; +}; ++
Requires: | For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +pointee<Dereferenceable>::type& shall be well-formed. +Otherwise iterator_traits<Dereferenceable>::reference shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of indirect_reference] | +
---|
type is determined according to the following algorithm, where +x is an object of type Dereferenceable:
++if ( ++x is ill-formed ) + return ``pointee<Dereferenceable>::type&`` +else + std::iterator_traits<Dereferenceable>::reference ++
template < class Iterator @@ -1256,17 +1526,14 @@ template < , class Difference = use_default > class indirect_iterator - : public iterator_adaptor< - indirect_iterator<Iterator, Value, Access, Traversal, - Reference, Difference>, - Iterator, - /* Value = see below */, - CategoryOrTraversal, - Reference, - Difference> { - friend class iterator_core_access; public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + indirect_iterator(); indirect_iterator(Iterator x); @@ -1280,54 +1547,92 @@ class indirect_iterator > const& y , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition ); -private: // as-if specification - typename indirect_iterator::reference dereference() const - { - return **this->base(); - } -}; -template <class Dereferenceable> -struct referent { - typedef /* see below */ type; + Iterator const& base() const; + reference operator*() const; + indirect_iterator& operator++(); + indirect_iterator& operator--(); +private: + Iterator m_iterator; // exposition };-
If Value is not use_default then the the argument for the -iterator_adaptor base class' Value parameter is Value with -cv-qualifiers removed. If Value is use_default, then the -argument for the iterator_adaptor base class' Value parameter -is computed as follows. We use the abbreviation -V=iterator_traits<Iterator>::value_type and v is an object of -type V.:
+The member types of indirect_iterator are defined according to +the following pseudo-code, where V is +iterator_traits<Iterator>::value_type
-if (*v returns a constant lvalue or an rvalue) then - referent<V>::type +if (Value is use_default) then + typedef remove_const<pointee<V>::type>::type value_type; else - add_const<referent<V>::type>::type --
The algorithm for the type member of referent traits class is -as follows:
--if (Dereferenceable is a class and has member element_type) - Dereferenceable::element_type + typedef remove_const<Value>::type value_type; + +if (Reference is use_default) then + if (Value is use_default) then + typedef indirect_reference<V>::type reference; + else + typedef Value& reference; else - iterator_traits<Dereferenceable>::value_type + typedef Reference reference; + +if (Value is use_default) then + typedef pointee<V>::type* pointer; +else + typedef Value* pointer; + +if (Difference is use_default) + typedef iterator_traits<Iterator>::difference_type difference_type; +else + typedef Difference difference_type; + +if (CategoryOrTraversal is use_default) + typedef iterator-category ( + iterator_traversal<Iterator>::type,``reference``,``value_type`` + ) iterator_category; +else + typedef iterator-category ( + CategoryOrTraversal,``reference``,``value_type`` + ) iterator_category;
The Iterator type must meet the requirements of Readable -Iterator. Also, the following requirements are placed on -iterator_traits<Iterator>::value_type. Let i be an object of -type iterator_traits<Iterator>::value_type. Then *i must be a -valid expression, and the type of *i must be the same as the -iterator_adaptor::reference. Also, there are further requirements -on the iterator_traits<Iterator>::value_type if the Value -parameter is not use_default, as implied by the algorithm for deducing -the default.
+The expression *v, where v is an object of +iterator_traits<Iterator>::value_type, shall be valid +expression and convertible to reference. Iterator shall +model the traversal concept indicated by iterator_category. +Value, Reference, and Difference shall be chosen so +that value_type, reference, and difference_type meet +the requirements indicated by iterator_category.
+[Note: there are further requirements on the +iterator_traits<Iterator>::value_type if the Value +parameter is not use_default, as implied by the algorithm for +deducing the default for the value_type member.]
+In addition to the concepts indicated by iterator_category +and by iterator_traversal<indirect_iterator>::type, a +specialization of indirect_iterator models the following +concepts, Where v is an object of +iterator_traits<Iterator>::value_type:
++++
+- Readable Iterator if reference(*v) is convertible to +value_type.
+- Writable Iterator if reference(*v) = t is a valid +expression (where t is an object of type +indirect_iterator::value_type)
+- Lvalue Iterator if reference is a reference type.
+
indirect_iterator<X,V1,C1,R1,D1> is interoperable with +indirect_iterator<Y,V2,C2,R2,D2> if and only if X is +interoperable with Y.
In addition to the operations required by the concepts described +above, specializations of indirect_iterator provide the +following operations.
indirect_iterator();
Requires: | Iterator must be Default Constructible. |
---|---|
Returns: | An instance of indirect_iterator with -a default-constructed iterator_adaptor subobject. | +
Effects: | Constructs an instance of indirect_iterator with +a default-constructed m_iterator. |
Iterator const& base() const;
+Returns: | m_iterator | +
---|
reference operator*() const;
+Returns: | **m_iterator | +
---|
indirect_iterator& operator++();
+Effects: | ++m_iterator | +
---|---|
Returns: | *this | +
indirect_iterator& operator--();
+Effects: | --m_iterator | +
---|---|
Returns: | *this |
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.
+The reverse iterator adaptor iterates through the adapted iterator +range in the opposite direction.
template <class Iterator> -class reverse_iterator : - public iterator_adaptor< reverse_iterator<Iterator>, Iterator > +class reverse_iterator { - friend class iterator_core_access; public: + typedef iterator_traits<Iterator>::value_type value_type; + typedef iterator_traits<Iterator>::reference reference; + typedef iterator_traits<Iterator>::pointer pointer; + typedef iterator_traits<Iterator>::difference_type difference_type; + typedef /* see below */ iterator_category; + reverse_iterator() {} explicit reverse_iterator(Iterator x) ; @@ -1398,34 +1745,72 @@ 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(); - } - + Iterator const& base() const; + reference operator*() const; + reverse_iterator& operator++(); + reverse_iterator& operator--(); +private: + Iterator m_iterator; // exposition };+
If Iterator models Random Access Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +bidirectional_iterator_tag. Otherwise, iterator_category is +convertible to input_iterator_tag.
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 must be a model of Bidirectional Traversal Iterator. The +type iterator_traits<Iterator>::reference must be the type of +*i, where i is an object of type Iterator.
+A specialization of reverse_iterator models the same iterator +traversal and iterator access concepts modeled by its Iterator +argument. In addition, it may model old iterator concepts +specified in the following table:
+If I models | +then reverse_iterator<I> models | +
---|---|
Readable Lvalue Iterator, +Bidirectional Traversal Iterator | +Bidirectional Iterator | +
Writable Lvalue Iterator, +Bidirectional Traversal Iterator | +Mutable Bidirectional Iterator | +
Readable Lvalue Iterator, +Random Access Traversal Iterator | +Random Access Iterator | +
Writable Lvalue Iterator, +Random Access Traversal Iterator | +Mutable Random Access Iterator | +
reverse_iterator<X> is interoperable with +reverse_iterator<Y> if and only if X is interoperable with +Y.
+In addition to the operations required by the concepts modeled by +reverse_iterator, reverse_iterator provides the following +operations.
reverse_iterator();
Requires: | Iterator must be Default Constructible. |
---|---|
Returns: | An instance of reverse_iterator with a -default constructed base object. | +
Effects: | Constructs an instance of reverse_iterator with m_iterator +default constructed. |
Iterator const& base() const;
+Returns: | m_iterator | +
---|
reference operator*() const;
+Effects: | + |
---|
+Iterator tmp = m_iterator; +return *--tmp; ++
reverse_iterator& operator++();
+Effects: | --m_iterator | +
---|---|
Returns: | *this | +
reverse_iterator& operator--();
+Effects: | ++m_iterator | +
---|---|
Returns: | *this |
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.
+The transform iterator adapts an iterator by modifying the +operator* to apply a function object to the result of +dereferencing the iterator and returning the result.
template <class UnaryFunction, @@ -1483,53 +1911,111 @@ 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: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef iterator_traits<Iterator>::difference_type difference_type; + typedef /* see below */ iterator_category; + transform_iterator(); transform_iterator(Iterator const& x, UnaryFunction f); template<class F2, class I2, class R2, class V2> transform_iterator( transform_iterator<F2, I2, R2, V2> const& t - , typename enable_if_convertible<I2, Iterator>::type* = 0 // exposition - , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition + , typename enable_if_convertible<I2, Iterator>::type* = 0 // exposition only + , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only ); - UnaryFunction functor() const; + Iterator const& base() const; + reference operator*() const; + transform_iterator& operator++(); + transform_iterator& operator--(); private: - typename transform_iterator::value_type dereference() const; - UnaryFunction m_f; + Iterator m_iterator; // exposition only + UnaryFunction m_f; // exposition only };+
If Reference is use_default then the reference member of +transform_iterator is +result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type. +Otherwise, reference is Reference.
+If Value is use_default then the value_type member is +remove_cv<remove_reference<reference> >::type. Otherwise, +value_type is Value.
+If Iterator models Readable Lvalue Iterator and if Iterator +models Random Access Traversal Iterator, then iterator_category is +convertible to random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator, then +iterator_category is convertible to +bidirectional_iterator_tag. Otherwise iterator_category is +convertible to forward_iterator_tag. If Iterator does not +model Readable Lvalue Iterator then iterator_category is +convertible to input_iterator_tag.
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 -following options that is also modeled by Iterator.
+The argument Iterator shall model Readable Iterator.
+The resulting transform_iterator models the most refined of the +following that is also modeled by Iterator.
-
- Writable Lvalue Iterator if result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type is a non-const reference.
-- Readable Lvalue Iterator if result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type is a const -reference.
+- Writable Lvalue Iterator if transform_iterator::reference is a non-const reference.
+- Readable Lvalue Iterator if transform_iterator::reference is a const reference.
- Readable Iterator otherwise.
The transform_iterator models the most refined standard traversal -concept that is modeled by Iterator.
-The reference type of transform_iterator is -result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type. -The value_type is remove_cv<remove_reference<reference> >::type.
+concept that is modeled by the Iterator argument. +If transform_iterator is a model of Readable Lvalue Iterator then +it models the following original iterator concepts depending on what +the Iterator argument models.
+If Iterator models | +then transform_iterator models | +
---|---|
Single Pass Iterator | +Input Iterator | +
Forward Traversal Iterator | +Forward Iterator | +
Bidirectional Traversal Iterator | +Bidirectional Iterator | +
Random Access Traversal Iterator | +Random Access Iterator | +
If transform_iterator models Writable Lvalue Iterator then it is a +mutable iterator (as defined in the old iterator requirements).
+transform_iterator<F1, X, R1, V1> is interoperable with +transform_iterator<F2, Y, R2, V2> if and only if X is +interoperable with Y.
In addition to the operations required by the concepts modeled by +transform_iterator, transform_iterator provides the following +operations.
transform_iterator();
typename transform_iterator::value_type dereference() const;
+Iterator const& base() const;
Returns: | m_f(transform_iterator::dereference()); | +
---|---|
Returns: | m_iterator | +
reference operator*() const;
+Returns: | m_f(*m_iterator) | +
---|
transform_iterator& operator++();
+Effects: | ++m_iterator | +
---|---|
Returns: | *this | +
transform_iterator& operator--();
+Effects: | --m_iterator | +
---|---|
Returns: | *this |
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 -predicate is applied to an element, if it returns true then the -element is retained and if it returns false then the element is -skipped over. When skipping over elements, it is necessary for the -filter adaptor to know when to stop so as to avoid going past the end -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.
+which some elements of the range are skipped. A predicate function +object controls which elements are skipped. When the predicate is +applied to an element, if it returns true then the element is +retained and if it returns false then the element is skipped +over. When skipping over elements, it is necessary for the filter +adaptor to know when to stop so as to avoid going past the end of the +underlying range. A filter iterator is therefore constructed with pair +of iterators indicating the range of elements in the unfiltered +sequence to be traversed.template <class Predicate, class Iterator> class filter_iterator - : public iterator_adaptor< - filter_iterator<Predicate, Iterator>, Iterator - , use_default - , /* see details */ - > { public: + typedef iterator_traits<Iterator>::value_type value_type; + typedef iterator_traits<Iterator>::reference reference; + typedef iterator_traits<Iterator>::pointer pointer; + typedef iterator_traits<Iterator>::difference_type difference_type; + typedef /* see below */ iterator_category; + filter_iterator(); filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); filter_iterator(Iterator x, Iterator end = Iterator()); @@ -1624,45 +2143,107 @@ class filter_iterator ); Predicate predicate() const; Iterator end() const; - - private: // as-if specification - void increment() - { - ++(this->base_reference()); - satisfy_predicate(); - } - - void satisfy_predicate() - { - while (this->base() != this->m_end && !this->m_predicate(*this->base())) - ++(this->base_reference()); - } - - Predicate m_predicate; - Iterator m_end; + Iterator const& base() const; + reference operator*() const; + filter_iterator& operator++(); +private: + Predicate m_pred; // exposition only + Iterator m_iter; // exposition only + Iterator m_end; // exposition only };-
If Iterator models Readable Lvalue Iterator and Forward Traversal +Iterator then iterator_category is convertible to +std::forward_iterator_tag. Otherwise iterator_category is +convertible to std::input_iterator_tag.
The base Iterator parameter must be a model of Readable -Iterator and Single Pass Iterator. The resulting -filter_iterator will be a model of Forward Traversal Iterator -if Iterator is, otherwise the filter_iterator will be a -model of Single Pass Iterator. The access category of the -filter_iterator will be the same as the access category of -Iterator.
- -The Predicate must be Assignable, Copy Constructible, and the -expression p(x) must be valid where p is an object of type +
The Iterator argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator.
+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 iterator_traits<Iterator>::value_type, and where the type of p(x) must be convertible to bool.
The concepts that filter_iterator models are dependent on which +concepts the Iterator argument models, as specified in the +following tables.
+If Iterator models | +then filter_iterator models | +
---|---|
Single Pass Iterator | +Single Pass Iterator | +
Forward Traversal Iterator | +Forward Traversal Iterator | +
If Iterator models | +then filter_iterator models | +
---|---|
Readable Iterator | +Readable Iterator | +
Writable Iterator | +Writable Iterator | +
Lvalue Iterator | +Lvalue Iterator | +
If Iterator models | +then filter_iterator models | +
---|---|
Readable Iterator, Single Pass Iterator | +Input Iterator | +
Readable Lvalue Iterator, Forward Traversal Iterator | +Forward Iterator | +
Writable Lvalue Iterator, Forward Traversal Iterator | +Mutable Forward Iterator | +
filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> +if and only if X is interoperable with Y.
+In addition to those operations required by the concepts that +filter_iterator models, filter_iterator provides the following +operations.
filter_iterator();
Requires: | Predicate and Iterator must be Default Constructible. |
---|---|
Returns: | a filter_iterator whose -predicate is a default constructed Predicate and -whose end is a default constructed Iterator. | +
Effects: | Constructs a filter_iterator whose``m_pred``, m_iter, and m_end +members are a default constructed. |
Iterator const& base() const;
+Returns: | m_iterator | +
---|
reference operator*() const;
+Returns: | *m_iter | +
---|
filter_iterator& operator++();
+Effects: | Increments m_iter and then continues to +increment m_iter until either m_iter == m_end +or m_pred(*m_iter) == true. | +
---|---|
Returns: | *this |
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 adapts an object by adding an operator* that +returns the current value of the object. All other iterator operations +are forwarded to the adapted object.
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: +public: + typedef Incrementable value_type; + typedef const Incrementable& reference; + typedef const Incrementable* pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + counting_iterator(); counting_iterator(counting_iterator const& rhs); - counting_iterator(Incrementable x); - private: - typename counting_iterator::reference dereference() const - { - return this->base_reference(); - } - }; + explicit counting_iterator(Incrementable x); + Incrementable const& base() const; + reference operator*() const; + counting_iterator& operator++(); + counting_iterator& operator--(); +private: + Incrementable m_inc; // exposition +}; ++
If the Difference argument is use_default then +difference_type is an unspecified signed integral +type. Otherwise difference_type is Difference.
+iterator_category is determined according to the following +algorithm:
++if (CategoryOrTraversal is not use_default) + return CategoryOrTraversal +else if (numeric_limits<Incrementable>::is_specialized) + return iterator-category( + random_access_traversal_tag, Incrementable, const Incrementable&) +else + return iterator-category( + iterator_traversal<Incrementable>::type, + Incrementable, const Incrementable&)
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.
-Furthermore, if you wish to create a counting iterator that is a Forward -Traversal Iterator, then the following expressions must be valid:
+The Incrementable argument shall be Copy Constructible and Assignable.
+If iterator_category is convertible to forward_iterator_tag +or forward_traversal_tag, the following must be well-formed:
Incrementable i, j; -++i // pre-increment -i == j // operator equal +++i; // pre-increment +i == j; // operator equal-
If you wish to create a counting iterator that is a -Bidirectional Traversal Iterator, then pre-decrement is also required:
+If iterator_category is convertible to +bidirectional_iterator_tag or bidirectional_traversal_tag, +the following expression must also be well-formed:
--i-
If you wish to create a counting iterator that is a Random Access -Traversal Iterator, then these additional expressions are also -required:
+If iterator_category is convertible to +random_access_iterator_tag or random_access_traversal_tag, +the following must must also be valid:
counting_iterator::difference_type n; -i += n -n = i - j -i < j +i += n; +n = i - j; +i < j;
Specializations of counting_iterator model Readable Lvalue +Iterator. In addition, they model the concepts corresponding to the +iterator tags to which their iterator_category is convertible. +Also, if CategoryOrTraversal is not use_default then +counting_iterator models the concept corresponding to the iterator +tag CategoryOrTraversal. Otherwise, if +numeric_limits<Incrementable>::is_specialized, then +counting_iterator models Random Access Traversal Iterator. +Otherwise, counting_iterator models the same iterator traversal +concepts modeled by Incrementable.
+counting_iterator<X,C1,D1> is interoperable with +counting_iterator<Y,C2,D2> if and only if X is +interoperable with Y.
+In addition to the operations required by the concepts modeled by +counting_iterator, counting_iterator provides the following +operations.
counting_iterator();
Returns: | A default constructed instance of counting_iterator. | +
---|---|
Requires: | Incrementable is Default Constructible. | +
Effects: | Default construct the member m_inc. |
counting_iterator(Incrementable x);
+explicit counting_iterator(Incrementable x);
Returns: | An instance of counting_iterator with its base -object copy constructed from x. | +
---|---|
Effects: | Construct member m_inc from x. | +
reference operator*() const;
+Returns: | m_inc | +
---|
counting_iterator& operator++();
+Effects: | ++m_inc | +
---|---|
Returns: | *this | +
counting_iterator& operator--();
+Effects: | --m_inc | +
---|---|
Returns: | *this | +
Incrementable const& base() const;
+Returns: | m_inc |
---|
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 @@ -1849,60 +2534,57 @@ iterator is that creating a conforming output iterator is non-trivial, particularly because the proper implementation usually requires a proxy object.
template <class UnaryFunction> class function_output_iterator { public: - typedef iterator_tag< - writable_iterator - , incrementable_traversal_tag - > iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; - explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + explicit function_output_iterator(); - struct output_proxy { - output_proxy(UnaryFunction& f); - template <class T> output_proxy& operator=(const T& value); - }; - output_proxy operator*(); + explicit function_output_iterator(const UnaryFunction& f); + + /* see below */ operator*(); function_output_iterator& operator++(); function_output_iterator& operator++(int); +private: + UnaryFunction m_f; // exposition only };
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. -The resulting function_output_iterator is a model of the Writable -and Incrementable Iterator concepts.
+UnaryFunction must be Assignable and Copy Constructible.
+function_output_iterator is a model of the Writable and +Incrementable Iterator concepts.
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
Returns: | An instance of function_output_iterator with -f stored as a data member. | +
---|---|
Effects: | Constructs an instance of function_output_iterator +with m_f constructed from f. |
output_proxy operator*();
+operator*();
Returns: | An instance of output_proxy constructed with -a copy of the unary function f. | +
---|---|
Returns: | An object r of unspecified type such that r = t +is equivalent to m_f(t) for all t. |
output_proxy(UnaryFunction& f);
-Returns: | An instance of output_proxy with f stored as -a data member. | -
---|
template <class T> output_proxy& operator=(const T& value);
-Effects: | -m_f(value); -return *this; -- |
-
---|
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 -predicate is applied to an element, if it returns true then the -element is retained and if it returns false then the element is -skipped over. When skipping over elements, it is necessary for the -filter adaptor to know when to stop so as to avoid going past the end -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.
template <class Predicate, class Iterator> class filter_iterator - : public iterator_adaptor< - filter_iterator<Predicate, Iterator>, Iterator - , use_default - , /* see details */ - > { public: + typedef iterator_traits<Iterator>::value_type value_type; + typedef iterator_traits<Iterator>::reference reference; + typedef iterator_traits<Iterator>::pointer pointer; + typedef iterator_traits<Iterator>::difference_type difference_type; + typedef /* see below */ iterator_category; + filter_iterator(); filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); filter_iterator(Iterator x, Iterator end = Iterator()); @@ -268,43 +86,107 @@ class filter_iterator ); Predicate predicate() const; Iterator end() const; - - private: // as-if specification - void increment() - { - ++(this->base_reference()); - satisfy_predicate(); - } - - void satisfy_predicate() - { - while (this->base() != this->m_end && !this->m_predicate(*this->base())) - ++(this->base_reference()); - } - - Predicate m_predicate; - Iterator m_end; + Iterator const& base() const; + reference operator*() const; + filter_iterator& operator++(); +private: + Predicate m_pred; // exposition only + Iterator m_iter; // exposition only + Iterator m_end; // exposition only };+
If Iterator models Readable Lvalue Iterator and Forward Traversal +Iterator then iterator_category is convertible to +std::forward_iterator_tag. Otherwise iterator_category is +convertible to std::input_iterator_tag.
+The base Iterator parameter must be a model of Readable -Iterator and Single Pass Iterator. The resulting -filter_iterator will be a model of Forward Traversal Iterator -if Iterator is, otherwise the filter_iterator will be a -model of Single Pass Iterator. The access category of the -filter_iterator will be the same as the access category of -Iterator.
- -The Predicate must be Assignable, Copy Constructible, and the -expression p(x) must be valid where p is an object of type +
The Iterator argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator.
+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 iterator_traits<Iterator>::value_type, and where the type of p(x) must be convertible to bool.
The concepts that filter_iterator models are dependent on which +concepts the Iterator argument models, as specified in the +following tables.
+If Iterator models | +then filter_iterator models | +
---|---|
Single Pass Iterator | +Single Pass Iterator | +
Forward Traversal Iterator | +Forward Traversal Iterator | +
If Iterator models | +then filter_iterator models | +
---|---|
Readable Iterator | +Readable Iterator | +
Writable Iterator | +Writable Iterator | +
Lvalue Iterator | +Lvalue Iterator | +
If Iterator models | +then filter_iterator models | +
---|---|
Readable Iterator, Single Pass Iterator | +Input Iterator | +
Readable Lvalue Iterator, Forward Traversal Iterator | +Forward Iterator | +
Writable Lvalue Iterator, Forward Traversal Iterator | +Mutable Forward Iterator | +
filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> +if and only if X is interoperable with Y.
+In addition to those operations required by the concepts that +filter_iterator models, filter_iterator provides the following +operations.
filter_iterator();
Requires: | Predicate and Iterator must be Default Constructible. |
---|---|
Returns: | a filter_iterator whose -predicate is a default constructed Predicate and -whose end is a default constructed Iterator. | +
Effects: | Constructs a filter_iterator whose``m_pred``, m_iter, and m_end +members are a default constructed. |
Iterator const& base() const;
+Returns: | m_iterator | +
---|
reference operator*() const;
+Returns: | *m_iter | +
---|
filter_iterator& operator++();
+Effects: | Increments m_iter and then continues to +increment m_iter until either m_iter == m_end +or m_pred(*m_iter) == true. | +
---|---|
Returns: | *this | +
+template <class Predicate, class Iterator> +filter_iterator<Predicate,Iterator> +make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); ++
Returns: | filter_iterator<Predicate,Iterator>(f, x, end) | +
---|
+template <class Predicate, class Iterator> +filter_iterator<Predicate,Iterator> +make_filter_iterator(Iterator x, Iterator end = Iterator()); ++
Returns: | filter_iterator<Predicate,Iterator>(x, end) | +
---|
This example uses filter_iterator and then +make_filter_iterator to output only the positive integers from an +array of integers. Then make_filter_iterator is is used to output +the integers greater than -2.
++struct is_positive_number { + bool operator()(int x) { return 0 < x; } +}; + +int main() +{ + int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; + const int N = sizeof(numbers_)/sizeof(int); + + typedef int* base_iterator; + base_iterator numbers(numbers_); + + // Example using filter_iterator + typedef boost::filter_iterator<is_positive_number, base_iterator> + FilterIter; + + is_positive_number predicate; + FilterIter filter_iter_first(predicate, numbers, numbers + N); + FilterIter filter_iter_last(predicate, numbers + N, numbers + N); + + std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " ")); + std::cout << std::endl; + + // Example using make_filter_iterator() + std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N), + boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N), + std::ostream_iterator<int>(std::cout, " ")); + std::cout << std::endl; + + // Another example using make_filter_iterator() + std::copy( + boost::make_filter_iterator( + std::bind2nd(std::greater<int>(), -2) + , numbers, numbers + N) + + , boost::make_filter_iterator( + std::bind2nd(std::greater<int>(), -2) + , numbers + N, numbers + N) + + , std::ostream_iterator<int>(std::cout, " ") + ); + + std::cout << std::endl; + + return boost::exit_success; +} ++
The output is:
++4 5 8 +4 5 8 +0 -1 4 5 8 ++
The source code for this example can be found here.
The function output iterator adaptor makes it easier to create custom +
template <class UnaryFunction> class function_output_iterator { public: - typedef iterator_tag< - writable_iterator - , incrementable_traversal_tag - > iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; - explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + explicit function_output_iterator(); - struct output_proxy { - output_proxy(UnaryFunction& f); - template <class T> output_proxy& operator=(const T& value); - }; - output_proxy operator*(); + explicit function_output_iterator(const UnaryFunction& f); + + /* see below */ operator*(); function_output_iterator& operator++(); function_output_iterator& operator++(int); +private: + UnaryFunction m_f; // exposition only };
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. -The resulting function_output_iterator is a model of the Writable -and Incrementable Iterator concepts.
+UnaryFunction must be Assignable and Copy Constructible.
+function_output_iterator is a model of the Writable and +Incrementable Iterator concepts.
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
Returns: | An instance of function_output_iterator with -f stored as a data member. | +
---|---|
Effects: | Constructs an instance of function_output_iterator +with m_f constructed from f. |
output_proxy operator*();
+operator*();
Returns: | An instance of output_proxy constructed with -a copy of the unary function f. | +
---|---|
Returns: | An object r of unspecified type such that r = t +is equivalent to m_f(t) for all t. |
output_proxy(UnaryFunction& f);
-Returns: | An instance of output_proxy with f stored as -a data member. | -
---|
template <class T> output_proxy& operator=(const T& value);
-Effects: | -m_f(value); -return *this; + |
-
---|
The iterator categories defined in C++98 are extremely limiting because they bind together two orthogonal concepts: traversal and element access. For example, because a random access iterator is @@ -275,71 +83,84 @@ iterators already in use which can't be adequately represented by the existing concepts. For details about the new iterator concepts, see our
-Standard Proposal For New-Style Iterators+Standard Proposal For New-Style Iterators (PDF)
Writing standard-conforming iterators is tricky, but the need comes up often. In order to ease the implementation of new iterators, -the Boost.Iterator library provides the iterator_facade class template, +the Boost.Iterator library provides the iterator_facade class template, which implements many useful defaults and compile-time checks -designed to help the author iterator ensure that his iterator is -correct. It is common to define a new iterator which behaves like -another iterator, but which modifies some aspect of its behavior. -For that purpose, the library supplies the iterator_adaptor class -template, which is specially designed to take advantage of as much -of the underlying iterator's behavior as possible.
-Both iterator_facade and iterator_adaptor as well as many of the specialized +designed to help the iterator author ensure that his iterator is +correct.
+It is also common to define a new iterator that is similar to some +underlying iterator or iterator-like type, but that modifies some +aspect of the underlying type's behavior. For that purpose, the +library supplies the iterator_adaptor class template, which is specially +designed to take advantage of as much of the underlying type's +behavior as possible.
+The documentation for these two classes can be found at the following +web pages:
+Both iterator_facade and iterator_adaptor as well as many of the specialized adaptors mentioned below have been proposed for standardization, and accepted into the first C++ technical report; see our
-Standard Proposal For Iterator Facade and Adaptor+Standard Proposal For Iterator Facade and Adaptor (PDF)
for more details.
The iterator library supplies a useful suite of standard-conforming iterator templates based on the Boost iterator facade and adaptor.
If you have been using the old Boost Iterator Adaptor library to implement iterators, you probably wrote a Policies class which captures the core operations of your iterator. In the new library @@ -349,7 +170,7 @@ you probably wrote a iterator_adaptor specialization you needed; in the new library design you don't need a type generator (though may want to keep it around as a compatibility aid for older code) because, due to the -use of the Curiously Recurring Template Pattern (CRTP) [Cop95], +use of the Curiously Recurring Template Pattern (CRTP) [Cop95], you can now define the iterator class yourself and acquire functionality through inheritance from iterator_facade or iterator_adaptor. As a result, you also get much finer control @@ -364,7 +185,7 @@ type, transform_iterator will projection_iterator used to.
In 2000 Dave Abrahams was writing an iterator for a container of pointers, which would access the pointed-to elements when dereferenced. Naturally, being a library writer, he decided to @@ -393,7 +214,7 @@ library you see today.
The indirect iterator adapts an iterator by applying an extra -dereference inside of operator*(). For example, this iterator -adaptor makes it possible to view a container of pointers -(e.g. list<foo*>) as if it were a container of the pointed-to type -(e.g. list<foo>) .
-template < class Iterator , class Value = use_default - , unsigned Access = use_default_access - , class Traversal = use_default + , class CategoryOrTraversal = use_default , class Reference = use_default , class Difference = use_default > class indirect_iterator - : public iterator_adaptor</* see discussion */> { - friend class iterator_core_access; public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + indirect_iterator(); indirect_iterator(Iterator x); + template < - class Iterator2, class Value2, unsigned Access2, class Traversal2 + class Iterator2, class Value2, class Category2 , class Reference2, class Difference2 > indirect_iterator( indirect_iterator< - Iterator2, Value2, Access2, Traversal2, Reference2, Difference2 + Iterator2, Value2, Category2, Reference2, Difference2 > const& y , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition ); -private: // as-if specification - typename indirect_iterator::reference dereference() const - { - return **this->base(); - } + + Iterator const& base() const; + reference operator*() const; + indirect_iterator& operator++(); + indirect_iterator& operator--(); +private: + Iterator m_iterator; // exposition };-
The value_type of the Iterator template parameter should -itself be dereferenceable. The return type of the operator* for -the value_type must be the same type as the Reference template -parameter. The Value template parameter will be the value_type -for the indirect_iterator, unless Value is const. If Value -is const X, then value_type will be non- const X. The -default for Value is
+The member types of indirect_iterator are defined according to +the following pseudo-code, where V is +iterator_traits<Iterator>::value_type
-iterator_traits< iterator_traits<Iterator>::value_type >::value_type +if (Value is use_default) then + typedef remove_const<pointee<V>::type>::type value_type; +else + typedef remove_const<Value>::type value_type; + +if (Reference is use_default) then + if (Value is use_default) then + typedef indirect_reference<V>::type reference; + else + typedef Value& reference; +else + typedef Reference reference; + +if (Value is use_default) then + typedef pointee<V>::type* pointer; +else + typedef Value* pointer; + +if (Difference is use_default) + typedef iterator_traits<Iterator>::difference_type difference_type; +else + typedef Difference difference_type; + +if (CategoryOrTraversal is use_default) + typedef iterator-category ( + iterator_traversal<Iterator>::type,``reference``,``value_type`` + ) iterator_category; +else + typedef iterator-category ( + CategoryOrTraversal,``reference``,``value_type`` + ) iterator_category;-
If the default is used for Value, then there must be a valid -specialization of iterator_traits for the value type of the base -iterator.
-The Reference parameter will be the reference type of the -indirect_iterator. The default is Value&.
-The Access and Traversal parameters are passed unchanged to -the corresponding parameters of the iterator_adaptor base -class, and the Iterator parameter is passed unchanged as the -Base parameter to the iterator_adaptor base class.
-The indirect iterator will model the most refined standard traversal -concept that is modeled by the Iterator type. The indirect -iterator will model the most refined standard access concept that is -modeled by the value type of Iterator.
+The expression *v, where v is an object of +iterator_traits<Iterator>::value_type, shall be valid +expression and convertible to reference. Iterator shall +model the traversal concept indicated by iterator_category. +Value, Reference, and Difference shall be chosen so +that value_type, reference, and difference_type meet +the requirements indicated by iterator_category.
+[Note: there are further requirements on the +iterator_traits<Iterator>::value_type if the Value +parameter is not use_default, as implied by the algorithm for +deducing the default for the value_type member.]
+In addition to the concepts indicated by iterator_category +and by iterator_traversal<indirect_iterator>::type, a +specialization of indirect_iterator models the following +concepts, Where v is an object of +iterator_traits<Iterator>::value_type:
++++
+- Readable Iterator if reference(*v) is convertible to +value_type.
+- Writable Iterator if reference(*v) = t is a valid +expression (where t is an object of type +indirect_iterator::value_type)
+- Lvalue Iterator if reference is a reference type.
+
indirect_iterator<X,V1,C1,R1,D1> is interoperable with +indirect_iterator<Y,V2,C2,R2,D2> if and only if X is +interoperable with Y.
In addition to the operations required by the concepts described +above, specializations of indirect_iterator provide the +following operations.
indirect_iterator();
Requires: | Iterator must be Default Constructible. |
---|---|
Returns: | An instance of indirect_iterator with -a default constructed base object. | +
Effects: | Constructs an instance of indirect_iterator with +a default-constructed m_iterator. |
Iterator const& base() const;
+Returns: | m_iterator | +
---|
reference operator*() const;
+Returns: | **m_iterator | +
---|
indirect_iterator& operator++();
+Effects: | ++m_iterator | +
---|---|
Returns: | *this | +
indirect_iterator& operator--();
+Effects: | --m_iterator | +
---|---|
Returns: | *this | +
This example prints an array of characters, using +indirect_iterator to access the array of characters through an +array of pointers. Next indirect_iterator is used with the +transform algorithm to copy the characters (incremented by one) to +another array. A constant indirect iterator is used for the source and +a mutable indirect iterator is used for the destination. The last part +of the example prints the original array of characters, but this time +using the make_indirect_iterator helper function.
++char characters[] = "abcdefg"; +const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char +char* pointers_to_chars[N]; // at the end. +for (int i = 0; i < N; ++i) + pointers_to_chars[i] = &characters[i]; + +// Example of using indirect_iterator + +boost::indirect_iterator<char**, char> + indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); + +std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ",")); +std::cout << std::endl; + + +// Example of making mutable and constant indirect iterators + +char mutable_characters[N]; +char* pointers_to_mutable_chars[N]; +for (int j = 0; j < N; ++j) + pointers_to_mutable_chars[j] = &mutable_characters[j]; + +boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars), + mutable_indirect_last(pointers_to_mutable_chars + N); +boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars), + const_indirect_last(pointers_to_chars + N); + +std::transform(const_indirect_first, const_indirect_last, + mutable_indirect_first, std::bind1st(std::plus<char>(), 1)); + +std::copy(mutable_indirect_first, mutable_indirect_last, + std::ostream_iterator<char>(std::cout, ",")); +std::cout << std::endl; + + +// Example of using make_indirect_iterator() + +std::copy(boost::make_indirect_iterator(pointers_to_chars), + boost::make_indirect_iterator(pointers_to_chars + N), + std::ostream_iterator<char>(std::cout, ",")); +std::cout << std::endl; ++
The output is:
++a,b,c,d,e,f,g, +b,c,d,e,f,g,h, +a,b,c,d,e,f,g, ++
The source code for this example can be found here.