From a982c4230376346de5e5620313cde00d136fbd32 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 22:47:15 +0000 Subject: [PATCH] Various updates and clarifications. [SVN r19106] --- doc/facade-and-adaptor.html | 2042 +++++++++++++++++++++++++++++++++++ doc/facade-and-adaptor.rst | 144 ++- doc/new-iter-concepts.html | 1133 +++++++++++++++++++ doc/new-iter-concepts.rst | 2 +- 4 files changed, 3264 insertions(+), 57 deletions(-) create mode 100755 doc/facade-and-adaptor.html create mode 100755 doc/new-iter-concepts.html diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html new file mode 100755 index 0000000..996ea4c --- /dev/null +++ b/doc/facade-and-adaptor.html @@ -0,0 +1,2042 @@ + + + + + + +Iterator Facade and Adaptor + + + + + + + +
+

Iterator Facade and Adaptor

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2003-07-12
Number:This document is a revised version of the official N1476=03-0059
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
abstract:We propose a set of class templates that help programmers +build standard-conforming iterators, both from scratch and +by adapting other iterators.
+
+

Table of Contents

+ +
+
+

Motivation

+

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 +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators 2, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies istream_iterator and +ostream_iterator for reading from and writing to streams, +insert_iterator, front_insert_iterator and +back_insert_iterator for inserting elements into containers, and +raw_storage_iterator for initializing raw memory [7].

+

Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types.

+

Although it is easy to create iterators that almost conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which actually conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +iterator_facade, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +iterator_facade also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the iterator_facade.

+

A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides reverse_iterator, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature:

+
    +
  • Checked iter[13] adds bounds-checking to an existing iterator.
  • +
  • The iterators of the View Template Library[14], which adapts +containers, are themselves adaptors over the underlying iterators.
  • +
  • Smart iterators [5] adapt an iterator's dereferencing behavior by +applying a function object to the object being referenced and +returning the result.
  • +
  • Custom iterators [4], in which a variety of adaptor types are enumerated.
  • +
  • Compound iterators [1], which access a slice out of a container of containers.
  • +
  • Several iterator adaptors from the MTL [12]. The MTL contains a +strided iterator, where each call to operator++() moves the +iterator ahead by some constant factor, and a scaled iterator, which +multiplies the dereferenced value by some constant.
  • +
+ + + + + +
[1]We use the term concept to mean a set of requirements +that a type must satisfy to be used with a particular template +parameter.
+ + + + + +
[2]The term mutable iterator refers to iterators over objects that +can be changed by assigning to the dereferenced iterator, while +constant iterator refers to iterators over objects that cannot be +modified.
+

To fulfill the need for constructing adaptors, we propose the +iterator_adaptor class template. Instantiations of +iterator_adaptor serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the transform_iterator that +applies some user-specified function during the dereference of the +iterator.

+
+
+

Impact on the Standard

+

This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts.

+
+
+

Design

+
+

Iterator Concepts

+

This proposal is formulated in terms of the new iterator concepts +as proposed in n1477, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories.

+

This proposal does not strictly depend on proposal n1477, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if n1477 was not accepted.

+
+
+

Interoperability

+

The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues.

+

Issue 179 concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +179, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available.

+

Issue 280 concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads.

+
+
+

Iterator Facade

+

While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:

+
    +
  • dereferencing
  • +
  • incrementing
  • +
  • decrementing
  • +
  • equality comparison
  • +
  • random-access motion
  • +
  • distance measurement
  • +
+

In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.

+

Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95] so that the user can specify the behavior of +iterator_facade in a derived class. Former designs used policy +objects to specify the behavior. The proposal does not use policy +objects for several reasons:

+
+
    +
  1. the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
  2. +
  3. The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
  4. +
  5. Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself means +that all iterators generated by iterator_facade would be +instantiations of iterator_facade. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
  6. +
+
+
+

Usage

+

The user of iterator_facade derives his iterator class from an +instantiation of iterator_facade which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to iterator_facade have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's value_type as iterator_facade's Value +parameter and omit the Reference parameter which follows.

+

The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionEffects
i.dereference()Access the value referred to
i.equal(j)Compare for equality with j
i.increment()Advance by one position
i.decrement()Retreat by one position
i.advance(n)Advance by n positions
i.distance_to(j)Measure the distance to j
+
+ +

In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.

+
+
+
+

Iterator Core Access

+

iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. This proposal frees the public interface of the derived +iterator type from any implementation detail.

+

Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.

+

In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, this proposal provides +iterator_core_access, a class that acts as a gateway to the core +member functions in the derived iterator class. The author of the +derived class only needs to grant friendship to +iterator_core_access to make his core member functions available +to the library.

+ + +

iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.

+
+
+

operator[]

+

The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.

+

Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1477: the result of p[n] is a proxy object +containing a copy of p+n, and p[n] = x is equivalent to *(p ++ n) = x. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an operator[] which returns an lvalue in the derived +iterator class; it will hide the one supplied by iterator_facade +from clients of her iterator.

+
+
+

operator->

+

The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.

+

This proposal does not explicitly specify the return type for +operator-> and operator[]. Instead it requires each +iterator_facade instantiation to meet the requirements of its +iterator_category.

+
+
+

Iterator Adaptor

+

The iterator_adaptor class template adapts some Base 3 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.

+ + + + + +
[3]The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor.
+

The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the table +above. The Base type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of iterator_adaptor that have not been +redefined in the user's derived class.

+

Several of the template parameters of iterator_adaptor default to +use_default. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and use_default can help to simplify the +implementation. Finally, use_default is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users making mistakes based on that +assumption.

+
+
+

Specialized Adaptors

+

This proposal also contains several examples of specialized adaptors +which were easily implemented using iterator_adaptor:

+
    +
  • indirect_iterator, which iterates over iterators, pointers, +or smart pointers and applies an extra level of dereferencing.
  • +
  • A new reverse_iterator, which inverts the direction of a Base +iterator's motion, while allowing adapted constant and mutable +iterators to interact in the expected ways (unlike those in most +implementations of C++98).
  • +
  • transform_iterator, which applies a user-defined function object +to the underlying values when dereferenced.
  • +
  • projection_iterator, which is similar to transform_iterator +except that when dereferenced it returns a reference instead of +a value.
  • +
  • filter_iterator, which provides a view of an iterator range in +which some elements of the underlying range are skipped.
  • +
+
    +
  • counting_iterator, which adapts any incrementable type +(e.g. integers, iterators) so that incrementing/decrementing the +adapted iterator and dereferencing it produces successive values of +the Base type.
  • +
  • function_output_iterator, which makes it easier to create custom +output iterators.
  • +
+

Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators).

+
+
+
+

Proposed Text

+
+

Header <iterator_helper> synopsis [lib.iterator.helper.synopsis]

+
+struct use_default;
+
+struct iterator_core_access { /* implementation detail */ };
+
+template <
+    class Derived
+  , class Value
+  , class AccessCategory
+  , class TraversalCategory
+  , class Reference  = Value&
+  , class Difference = ptrdiff_t
+>
+class iterator_facade;
+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class Category   = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor;
+
+template <
+    class Iterator
+  , class Value = use_default
+  , class Category = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator;
+
+template <class Iterator>
+class reverse_iterator;
+
+template <
+    class UnaryFunction
+  , class Iterator
+  , class Reference = use_default
+  , class Value = use_default
+>
+class transform_iterator;
+
+template <class Predicate, class Iterator>
+class filter_iterator;
+
+template <
+    class Incrementable
+  , class Category = use_default
+  , class Difference = use_default
+>
+class counting_iterator
+
+template <class UnaryFunction>
+class function_output_iterator;
+
+
+
+

Iterator facade [lib.iterator.facade]

+

iterator_facade is a base class template which implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.

+
+

Class template iterator_facade

+
+template <
+    class Derived
+  , class Value
+  , class AccessCategory
+  , class TraversalCategory
+  , class Reference  = /* see below */
+  , class Difference = ptrdiff_t
+>
+class iterator_facade {
+public:
+    typedef remove_cv<Value>::type value_type;
+    typedef Reference reference;
+    typedef /* see description of operator-> */ pointer;
+    typedef Difference difference_type;
+    typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
+
+    reference operator*() const;
+    /* see below */ operator->() const;
+    /* see below */ operator[](difference_type n) const;
+    Derived& operator++();
+    Derived operator++(int);
+    Derived& operator--();
+    Derived operator--(int);
+    Derived& operator+=(difference_type n);
+    Derived& operator-=(difference_type n);
+    Derived operator-(difference_type n) const;
+};
+
+// Comparison operators
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition
+operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+            iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator difference
+template <class Dr1, class V1, class AC1, class TC1, class R1, class D1,
+          class Dr2, class V2, class AC2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1, Dr2, bool>::type
+operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs,
+           iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs);
+
+// Iterator addition
+template <class Derived, class V, class AC, class TC, class R, class D>
+Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&,
+                   typename Derived::difference_type n)
+
+

[Note: The enable_if_interoperable template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, by +which we mean they are convertible to each other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.]

+ +
+
+

iterator_facade requirements

+

The Derived template parameter must be a class derived from +iterator_facade.

+

The default for the Reference parameter is Value& if the +access category for iterator_facade is implicitly convertible to +writable_iterator_tag, and const Value& otherwise.

+

The following table describes the other requirements on the +Derived parameter. Depending on the resulting iterator's +iterator_category, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class iterator_core_access.

+

In the table below, X is the derived iterator type, a is an +object of type X, b and c are objects of type const X, +n is an object of X::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.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/NoteRequired to implement +Iterator Concept(s)
c.dereference()X::reference Readable Iterator, Writable +Iterator
c.equal(b)convertible to booltrue iff b and c are +equivalent.Single Pass Iterator
c.equal(y)convertible to booltrue iff c and y refer to the +same position. Implements c == y +and c != y.Single Pass Iterator
a.advance(n)unused Random Access Traversal +Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal +Iterator
c.distance_to(b)convertible to +X::difference_typeequivalent to distance(c, b)Random Access Traversal +Iterator
c.distance_to(z)convertible to +X::difference_typeequivalent to distance(c, z). +Implements c - z, c < z, c +<= z, c > z, and c >= c.Random Access Traversal +Iterator
+ +
+
+

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 +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If X::reference is a reference type, returns an object +of type X::pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, given an +object a of type X, a->m is equivalent to (w = *a, +w.m) for some temporary object w of type X::value_type.

+

The type X::pointer is Value* if the access category for +X is implicitly convertible to writable_iterator_tag, and +Value const* otherwise.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to X::reference and holding a copy +p of a+n such that, for a constant object v of type +X::value_type, X::reference(a[n] = v) is equivalent +to p = v.
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *this;
+
+
+ +

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *this;
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *this;
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *this;
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + + + +
Effects:Derived tmp(static_cast<Derived const*>(this)); +return tmp -= n;
Returns:static_cast<Derived const*>(this)->advance(-n);
+
+
+
+

Iterator adaptor [lib.iterator.adaptor]

+

The iterator_adaptor is a base class template derived from an +instantiation of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.

+
+

Class template iterator_adaptor

+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class Category   = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor 
+  : public iterator_facade<Derived, /* see details ...*/>
+{
+    friend class iterator_core_access;
+ public:
+    iterator_adaptor();
+    explicit iterator_adaptor(Base iter);
+    Base base() const;
+ protected:
+    Base const& base_reference() const;
+    Base& base_reference();
+ private: // Core iterator interface for iterator_facade.  
+    typename iterator_adaptor::reference dereference() const;
+
+    template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+    void advance(typename iterator_adaptor::difference_type n);
+    void increment();
+    void decrement();
+
+    template <
+        class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >   
+    typename iterator_adaptor::difference_type distance_to(
+        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ private:
+    Base m_iterator;
+};
+
+
+
+

iterator_adaptor requirements

+

The Derived template parameter must be a derived class of +iterator_adaptor. The Base type must implement the expressions +involving m_iterator in the specifications of those private member +functions of iterator_adaptor that are not redefined by the +Derived class and that are needed to model the concept +corresponding to the chosen Category according to the requirements +of iterator_facade. The rest of the template parameters specify +the types for the member typedefs in iterator_facade. The +following pseudo-code specifies the traits types for +iterator_adaptor.

+
+if (Value == use_default)
+    value_type = iterator_traits<Base>::value_type;
+else 
+    value_type = remove_cv<Value>::type;
+
+if (Reference == use_default) {
+    if (Value == use_default)
+        reference = iterator_traits<Base>::reference;
+    else 
+        reference = Value&;
+} else
+    reference = Reference;
+
+if (Distance == use_default)
+    difference_type = iterator_traits<Base>::difference_type;
+else
+    difference_type = Distance;
+
+if (Category == use_default)
+    iterator_category = iterator_tag< 
+        access_category< 
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >,
+        traversal_category<
+            iterator< iterator_traits<Base>::iterator_category,
+                      Value,
+                      Distance,
+                      Value*,
+                      Reference > >
+else
+    iterator_category = Category;
+
+ +
+
+

iterator_adaptor public operations

+

iterator_adaptor();

+ +++ + + + + + +
Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with +m_iterator default constructed.
+

explicit iterator_adaptor(Base iter);

+ +++ + + + +
Returns:An instance of iterator_adaptor with +m_iterator copy constructed from iter.
+

Base base() const;

+ +++ + + + +
Returns:m_iterator
+
+
+

iterator_adaptor protected member functions

+

Base const& base_reference() const;

+ +++ + + + +
Returns:A const reference to m_iterator.
+

Base& base_reference();

+ +++ + + + +
Returns:A non-const reference to m_iterator.
+
+
+

iterator_adaptor private member functions

+

typename iterator_adaptor::reference dereference() const;

+ +++ + + + +
Returns:*m_iterator
+
+template <
+class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+ +++ + + + +
Returns:m_iterator == x.base()
+

void advance(typename iterator_adaptor::difference_type n);

+ +++ + + + +
Effects:m_iterator += n;
+

void increment();

+ +++ + + + +
Effects:++m_iterator;
+

void decrement();

+ +++ + + + +
Effects:--m_iterator;
+
+template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>   
+typename iterator_adaptor::difference_type distance_to(
+    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ +++ + + + +
Returns:y.base() - m_iterator
+
+
+
+

Specialized adaptors [lib.iterator.special.adaptors]

+ +

[Note: The enable_if_convertible<X,Y>::type expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type X is implicitly convertible to an object of +type Y. The enable_if_convertible approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible.]

+
+

Indirect iterator

+

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

+ +
+

Class template indirect_iterator

+
+template <
+    class Iterator
+  , class Value = use_default
+  , class Category = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator
+  : public iterator_adaptor</* see discussion */>
+{
+    friend class iterator_core_access;
+ public:
+    indirect_iterator();
+    indirect_iterator(Iterator x);
+    template <
+        class Iterator2, class Value2, class Category2
+      , class Reference2, class Difference2
+    >
+    indirect_iterator(
+        indirect_iterator<
+             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();
+    }
+};
+
+
+
+

indirect_iterator requirements

+

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

+
+iterator_traits< iterator_traits<Iterator>::value_type >::value_type
+
+

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 Category parameter is the iterator_category type for the +indirect_iterator. The default is +iterator_traits<Iterator>::iterator_category.

+

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.

+
+
+

indirect_iterator operations

+

indirect_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of indirect_iterator with +a default constructed base object.
+

indirect_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of indirect_iterator with +the iterator_adaptor subobject copy constructed from x.
+
+template <
+    class Iterator2, class Value2, class Category2
+  , class Reference2, class Difference2
+>
+indirect_iterator(
+    indirect_iterator<
+         Iterator2, Value2, Category2, Reference2, Difference2
+    > const& y
+  , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:Iterator2 is implicitly convertible to Iterator.
Returns:An instance of indirect_iterator that is a copy of y.
+
+
+
+

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

+
+template <class Iterator>
+class reverse_iterator :
+  public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
+{
+  friend class iterator_core_access;
+public:
+  reverse_iterator() {}
+  explicit reverse_iterator(Iterator x) ;
+
+  template<class OtherIterator>
+  reverse_iterator(
+      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();
+  }
+
+};
+
+
+
+

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.

+

reverse_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Returns:An instance of reverse_iterator with a +default constructed base object.
+

explicit reverse_iterator(Iterator x);

+ +++ + + + +
Returns:An instance of reverse_iterator with a +base object copy constructed from x.
+
+template<class OtherIterator>
+reverse_iterator(
+    reverse_iterator<OtherIterator> const& r
+  , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:An instance of reverse_iterator that is a copy of r.
+
+
+
+

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

+
+template <class AdaptableUnaryFunction,
+          class Iterator, 
+          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, AdaptableUnaryFunction f);
+
+  template<class OtherIterator, class R2, class V2>
+  transform_iterator(
+        transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+      , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+
+  AdaptableUnaryFunction functor() const;
+private:
+  typename transform_iterator::value_type dereference() const;
+  AdaptableUnaryFunction m_f;
+};
+
+
+
+

transform_iterator requirements

+

The type AdaptableUnaryFunction must be Assignable, Copy +Constructible, and the expression f(x) must be valid where f +is an object of type AdaptableUnaryFunction, x is an object of +type AdaptableUnaryFunction::argument_type, and where the type of +f(x) must be AdaptableUnaryFunction::result_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.

+
+
    +
  • Writable Lvalue Iterator if the result_type of the +AdaptableUnaryFunction is a non-const reference.
  • +
  • Readable Lvalue Iterator if the result_type is a const +reference.
  • +
  • Readable Iterator otherwise.
  • +
+
+

The transform_iterator models the most refined standard traversal +concept that is modeled by Iterator.

+

The value_type of transform_iterator is +remove_reference<result_type>::type. The reference type is +result_type.

+
+
+

transform_iterator public operations

+

transform_iterator();

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +and m_iterator default constructed.
+

transform_iterator(Iterator const& x, AdaptableUnaryFunction f);

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x.
+
+template<class OtherIterator, class R2, class V2>
+transform_iterator(
+      transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Returns:An instance of transform_iterator that is a copy of t.
Requires:OtherIterator is implicitly convertible to Iterator.
+

AdaptableUnaryFunction functor() const;

+ +++ + + + +
Returns:m_f
+
+
+

transform_iterator private operations

+

typename transform_iterator::value_type dereference() const;

+ +++ + + + +
Returns:m_f(transform_iterator::dereference());
+
+
+
+

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

+
+

Class template filter_iterator

+
+template <class Predicate, class Iterator>
+class filter_iterator
+    : public iterator_adaptor<
+          filter_iterator<Predicate, Iterator>, Iterator
+        , use_default
+        , /* see details */
+      >
+{
+ public:
+    filter_iterator();
+    filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+    filter_iterator(Iterator x, Iterator end = Iterator());
+    template<class OtherIterator>
+    filter_iterator(
+        filter_iterator<Predicate, OtherIterator> const& t
+        , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+        );
+    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;
+};
+
+
+
+
+

filter_iterator requirements

+

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 most refined +standard access category that is modeled by Iterator.

+ +

The Predicate 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.

+
+
+

filter_iterator 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.
+

filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

+ +++ + + + +
Returns:A filter_iterator at position x that filters according +to predicate f and that will not increment past end.
+

filter_iterator(Iterator x, Iterator end = Iterator());

+ +++ + + + + + +
Requires:Predicate must be Default Constructible.
Returns:A filter_iterator at position x that filters +according to a default constructed Predicate +and that will not increment past end.
+
+template <class OtherIterator>
+filter_iterator(
+    filter_iterator<Predicate, OtherIterator> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+    );``
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Returns:A copy of iterator t.
+

Predicate predicate() const;

+ +++ + + + +
Returns:A copy of the predicate object used to construct *this.
+

Iterator end() const;

+ +++ + + + +
Returns:The object end used to construct *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.

+
+

Class template counting_iterator

+
+template <class Incrementable, class Category = use_default, class Difference = use_default>
+class counting_iterator
+  : public iterator_adaptor<
+        counting_iterator<Incrementable, Category, Difference>
+      , Incrementable
+      , Incrementable
+      , /* see details for 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);
+ private:
+    typename counting_iterator::reference dereference() const
+    {
+        return this->base_reference();
+    }
+  };
+
+
+
[Note: implementers are encouraged to provide an implementation of
+
distance_to and a difference_type that avoids overflows in +the cases when the Incrementable type is a numeric type.]
+
+
+
+
+

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.

+

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

+
+Incrementable i, j;
+++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:

+
+--i
+
+

If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required:

+
+counting_iterator::difference_type n;
+i += n
+n = i - j
+i < j
+
+
+
+

counting_iterator operations

+

counting_iterator();

+ +++ + + + +
Returns:A default constructed instance of counting_iterator.
+

counting_iterator(counting_iterator const& rhs);

+ +++ + + + +
Returns:An instance of counting_iterator that is a copy of rhs.
+

counting_iterator(Incrementable x);

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

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 +passed as an argument to the unary function. The motivation for this +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

+
+template <class UnaryFunction>
+class function_output_iterator {
+public:
+  typedef iterator_tag<
+        writable_iterator_tag
+      , incrementable_traversal_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());
+
+  struct output_proxy {
+    output_proxy(UnaryFunction& f);
+    template <class T> output_proxy& operator=(const T& value);
+  };
+  output_proxy operator*();
+  function_output_iterator& operator++();
+  function_output_iterator& operator++(int);
+};
+
+
+
+
+

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. +The resulting function_output_iterator is a model of the Writable +and Incrementable Iterator concepts.

+
+
+

function_output_iterator operations

+

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

+ +++ + + + +
Returns:An instance of function_output_iterator with +f stored as a data member.
+

output_proxy operator*();

+ +++ + + + +
Returns:An instance of output_proxy constructed with +a copy of the unary function f.
+

function_output_iterator& operator++();

+ +++ + + + +
Returns:*this
+

function_output_iterator& operator++(int);

+ +++ + + + +
Returns:*this
+
+
+

function_output_iterator::output_proxy operations

+

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; 
+
+
+ + ++ + + +
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+ +
+
+
+
+ + + + diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst index 321c9e2..3c71e97 100644 --- a/doc/facade-and-adaptor.rst +++ b/doc/facade-and-adaptor.rst @@ -8,7 +8,7 @@ Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1476=03-0059 +:Number: **This document is a revised version of the official** N1476=03-0059 :copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com @@ -202,28 +202,40 @@ objects for several reasons: iterators, and a separate ``iterator_adaptor`` layer would be impossible. +Usage +----- + The user of ``iterator_facade`` derives his iterator class from an -instantiation of ``iterator_facade`` and defines member functions -implementing the core behaviors. The following table describes +instantiation of ``iterator_facade`` which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to ``iterator_facade`` have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's ``value_type`` as ``iterator_facade``\ 's ``Value`` +parameter and omit the ``Reference`` parameter which follows. + +The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes expressions which are required to be valid depending on the category of the derived iterator type. These member functions are described -briefly below and in more detail in the `iterator facade requirements`_. +briefly below and in more detail in the `iterator facade +requirements`_. - +----------------------------------------+-------------------------------------------+ - | Expression | Effects | - +========================================+===========================================+ - | ``i.dereference()`` | Access the value referred to | - +----------------------------------------+-------------------------------------------+ - | ``i.equal(j)`` | Compare for equality with ``j`` | - +----------------------------------------+-------------------------------------------+ - | ``i.increment()`` | Advance by one position | - +----------------------------------------+-------------------------------------------+ - | ``i.decrement()`` | Retreat by one position | - +----------------------------------------+-------------------------------------------+ - | ``i.advance(n)`` | Advance by ``n`` positions | - +----------------------------------------+-------------------------------------------+ - | ``i.distance_to(j)`` | Measure the distance to ``j`` | - +----------------------------------------+-------------------------------------------+ + +------------------------+-------------------------------+ + |Expression |Effects | + +========================+===============================+ + |``i.dereference()`` |Access the value referred to | + +------------------------+-------------------------------+ + |``i.equal(j)`` |Compare for equality with ``j``| + +------------------------+-------------------------------+ + |``i.increment()`` |Advance by one position | + +------------------------+-------------------------------+ + |``i.decrement()`` |Retreat by one position | + +------------------------+-------------------------------+ + |``i.advance(n)`` |Advance by ``n`` positions | + +------------------------+-------------------------------+ + |``i.distance_to(j)`` |Measure the distance to ``j`` | + +------------------------+-------------------------------+ .. Should we add a comment that a zero overhead implementation of iterator_facade is possible with proper inlining? @@ -236,8 +248,9 @@ type ``X`` is meant to be automatically interoperate with another iterator type ``Y`` (as with constant and mutable iterators) then there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` to ``X`` (but not both), typically implemented as a conversion -constructor. Also, if the iterator is to model Forward Traversal -Iterator, a default constructor is required. +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required. @@ -306,6 +319,8 @@ from clients of her iterator. .. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 +.. _`operator arrow`: + ``operator->`` ============== @@ -355,7 +370,7 @@ implementation. Finally, ``use_default`` is not left unspecified because specification helps to highlight that the ``Reference`` template parameter may not always be identical to the iterator's ``reference`` type, and will keep users making mistakes based on that -assumtion. +assumption. Specialized Adaptors ==================== @@ -480,27 +495,27 @@ and associated types, to be supplied by a derived iterator class. Class template ``iterator_facade`` ---------------------------------- -:: +.. parsed-literal:: template < class Derived , class Value , class AccessCategory , class TraversalCategory - , class Reference = /* see below */ + , class Reference = /* see below__ \*/ , class Difference = ptrdiff_t > class iterator_facade { public: typedef remove_cv::type value_type; typedef Reference reference; - typedef /* see description of operator-> */ pointer; + typedef /* see `description of operator->`__ \*/ pointer; typedef Difference difference_type; typedef iterator_tag iterator_category; - reference operator*() const; - /* see below */ operator->() const; - /* impl defined */ operator[](difference_type n) const; + reference operator\*() const; + /* see below__ \*/ operator->() const; + /* see below__ \*/ operator[](difference_type n) const; Derived& operator++(); Derived operator++(int); Derived& operator--(); @@ -566,6 +581,14 @@ Class template ``iterator_facade`` typename Derived::difference_type n) +__ `iterator facade requirements`_ + +__ `operator arrow`_ + +__ `operator arrow`_ + +__ brackets_ + [*Note:* The ``enable_if_interoperable`` template used above is for exposition purposes. The member operators should be only be in an overload set provided the derived types ``Dr1`` and ``Dr2`` are interoperable, by @@ -602,30 +625,35 @@ 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 | Return Type | Assertion/Note/Precondition/Postcondition | Required to implement Iterator Concept(s) | -| | | | | -+========================================+========================================+=================================================+===========================================+ -| ``c.dereference()`` | ``X::reference`` | | 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 | Single Pass Iterator | -| | |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 | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.distance_to(b)`` | convertible to X::difference_type | equivalent to ``distance(c, b)`` | Random Access Traversal Iterator | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ -| ``c.distance_to(z)`` | convertible to X::difference_type |equivalent to ``distance(c, z)``. Implements ``c| Random Access Traversal Iterator | -| | |- z``, ``c < z``, ``c <= z``, ``c > z``, and ``c | | -| | |>= c``. | | -+----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ - ++--------------------+-------------------+-------------------------------------+---------------------------+ +|Expression |Return Type |Assertion/Note |Required to implement | +| | | |Iterator Concept(s) | ++====================+===================+=====================================+===========================+ +|``c.dereference()`` |``X::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 | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.distance_to(b)``|convertible to |equivalent to ``distance(c, b)`` |Random Access Traversal | +| |X::difference_type | |Iterator | ++--------------------+-------------------+-------------------------------------+---------------------------+ +|``c.distance_to(z)``|convertible to |equivalent to ``distance(c, z)``. |Random Access Traversal | +| |X::difference_type |Implements ``c - z``, ``c < z``, ``c |Iterator | +| | |<= z``, ``c > z``, and ``c >= c``. | | ++--------------------+-------------------+-------------------------------------+---------------------------+ .. We should explain more about how the functions in the interface of iterator_facade @@ -644,7 +672,9 @@ through member functions of class ``iterator_core_access``. :Returns: ``static_cast(this)->dereference()`` -*see below* ``operator->() const;`` +``operator->() const;`` (see below__) + +__ `operator arrow`_ :Returns: If ``X::reference`` is a reference type, returns an object of type ``X::pointer`` equal to:: @@ -660,6 +690,8 @@ through member functions of class ``iterator_core_access``. ``Value const*`` otherwise. +.. _brackets: + *unspecified* ``operator[](difference_type n) const;`` :Returns: an object convertible to ``X::reference`` and holding a copy @@ -765,7 +797,7 @@ core interface functions of ``iterator_facade`` are redefined in the Class template ``iterator_adaptor`` ----------------------------------- -:: +.. parsed-literal:: template < class Derived @@ -776,7 +808,7 @@ Class template ``iterator_adaptor`` , class Difference = use_default > class iterator_adaptor - : public iterator_facade + : public iterator_facade { friend class iterator_core_access; public: @@ -808,7 +840,7 @@ Class template ``iterator_adaptor`` Base m_iterator; }; - +__ : ``iterator_adaptor`` requirements --------------------------------- diff --git a/doc/new-iter-concepts.html b/doc/new-iter-concepts.html new file mode 100755 index 0000000..765a733 --- /dev/null +++ b/doc/new-iter-concepts.html @@ -0,0 +1,1133 @@ + + + + + + +New Iterator Concepts + + + + + + + +
+

New Iterator Concepts

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction
Date:2003-07-12
Number:This document is a revised version of the official N1477=03-0060
Copyright:Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
+ +++ + + + +
Abstract:We propose a new system of iterator concepts that treat +access and positioning independently. This allows the +concepts to more closely match the requirements +of algorithms and provides better categorizations +of iterators that are used in practice. This proposal +is a revision of paper n1297.
+ +
+

Motivation

+

The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: iterator traversal and value access. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories.

+ ++++ + + + + + + + + + + + + + + +
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue 200 +is resolved)
Random Access Iteratori[n] is convertible to T (also i[n] = t +is required for mutable iterators once issue 299 +is resolved)
+

Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, vector<bool>::iterator is almost a +random access iterator, but the return type is not bool& (see +issue 96 and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of vector<bool> only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that at least one implementation erroneously assigns +random_access_iterator_tag as its iterator_category.

+

Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see transform_iterator). +For unary functions such as times, the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from operator*, if you +wrap int* with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator.

+

A third example is found in the vertex and edge iterators of the +Boost Graph Library. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is input_iterator_tag, which means that, +strictly speaking, you could not use these iterators with algorithms +like min_element(). As a temporary solution, the concept +Multi-Pass Input Iterator was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed.

+

In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen:

+
    +
  • Iterators are often mis-categorized.
  • +
  • Algorithm requirements are more strict than necessary, because they +cannot separate the need for random access or bidirectional +traversal from the need for a true reference return type.
  • +
+
+
+

Impact on the Standard

+

The new iterator concepts are backward-compatible with the old +iterator requirements, and old iterators are forward-compatible with +the new iterator concepts. That is to say, iterators that satisfy the +old requirements also satisfy appropriate concepts in the new system, +and iterators modeling the new concepts will automatically satisfy the +appropriate old requirements.

+ + +

The algorithms in the standard library benefit from the new iterator +concepts because the new concepts provide a more accurate way to +express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. The +following lists the proposed changes to the type requirements of +algorithms.

+

Forward Iterator -> Forward Traversal Iterator and Readable Iterator

+
+find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element
+

Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

+
+find_first_of
+

Forward Iterator -> Readable Iterator and Writable Iterator

+
+iter_swap
+

Forward Iterator -> Single Pass Iterator and Writable Iterator

+
+fill, generate
+

Forward Iterator -> Forward Traversal Iterator and Swappable Iterator

+
+rotate
+

Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator

+
+swap_ranges
+
+
Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator
+
remove, remove_if, unique
+
+

Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator

+
+replace, replace_if
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator
+
reverse
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator
+
partition
+
+

Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator

+
+copy_backwards
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator
+
next_permutation, prev_permutation
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator
+
stable_partition, inplace_merge
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
+
reverse_copy
+
Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator
+
random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap +make_heap, sort_heap
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
equal
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
transform
+
+
+
+

Design

+

The iterator requirements are be separated into two hierarchies. One +set of concepts handles the syntax and semantics of value access:

+
    +
  • Readable Iterator
  • +
  • Writable Iterator
  • +
  • Swappable Iterator
  • +
  • Readable Lvalue Iterator
  • +
  • Writable Lvalue Iterator
  • +
+

The refinement relationships among these iterator concepts are given +in the following diagram.

+

access.png

+

The access concepts describe requirements related to operator* and +operator->, including the value_type, reference, and +pointer associated types.

+

The other set of concepts handles traversal:

+
    +
  • Incrementable Iterator
  • +
  • Single Pass Iterator
  • +
  • Forward Traversal Iterator
  • +
  • Bidirectional Traversal Iterator
  • +
  • Random Access Traversal Iterator
  • +
+

The refinement relationships for the traversal concepts are in the +following diagram.

+

traversal.png

+

In addition to the iterator movement operators, such as +operator++, the traversal concepts also include requirements on +position comparison such as operator== and operator<. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements.

+

The relationship between the new iterator concepts and the old are +given in the following diagram.

+

oldeqnew.png

+

Like the old iterator requirements, we provide tags for purposes of +dispatching. There are two hierarchies of tags, one for the access +concepts and one for the traversal concepts. We provide an access +mechanism for mapping iterator types to these new tags. Our design +reuses iterator_traits<Iter>::iterator_category as the access +mechanism. To enable this, a pair of access and traversal tags are +combined into a single type using the following iterator_tag class.

+
+template <class AccessTag, class TraversalTag>
+struct iterator_tag : /* appropriate old category or categories */
+{
+  typedef AccessTag access;
+  typedef TraversalTag traversal;
+};
+
+

The iterator_tag class template is derived from the appropriate +iterator tag or tags from the old requirements based on the new-style +tags passed as template parameters. The algorithm for determining the +old tag or tags from the new tags picks the least-refined old concepts +that include all of the requirements of the access and traversal +concepts (that is, the closest fit), if any such category exists. For +example, a the category tag for a Readable Single Pass Iterator will +always be derived from input_iterator_tag, while the category tag +for a Single Pass Iterator that is both Readable and Writable will be +derived from both input_iterator_tag and output_iterator_tag.

+

We also provide two helper classes that make it convenient to obtain +the access and traversal tags of an iterator. These helper classes +work both for iterators whose iterator_category is +iterator_tag and also for iterators using the original iterator +categories.

+
+template <class Iterator> struct access_category { typedef ... type; };
+template <class Iterator> struct traversal_category { typedef ... type; };
+
+

The most difficult design decision concerned the operator[]. The +direct approach for specifying operator[] would have a return type +of reference; the same as operator*. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of issue 299: operator[] is +only required to return something convertible to the value_type +(for a Readable Iterator), and is required to support assignment +i[n] = t (for a Writable Iterator).

+
+
+

Proposed Text

+
+

Addition to [lib.iterator.requirements]

+
+

Iterator Value Access Concepts [lib.iterator.value.access]

+

In the tables below, X is an iterator type, a is a constant +object of type X, T is +std::iterator_traits<X>::value_type, and v is a constant +object of type T.

+
+

Readable Iterators [lib.readable.iterators]

+

A class or built-in type X models the Readable Iterator concept +for the value type T if the following expressions are valid and +respect the stated semantics. U is the type of any specified +member of type T.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Readable Iterator Requirements (in addition to CopyConstructible)
ExpressionReturn TypeAssertion/Note/Precondition/Postcondition
iterator_traits<X>::value_typeTAny non-reference, non-cv-qualified type
iterator_traits<X>::referenceConvertible to +iterator_traits<X>::value_type 
access_category<X>::typeConvertible to +readable_iterator_tag 
*aiterator_traits<X>::referencepre: a is dereferenceable. If a == +b then *a is equivalent to *b
a->mU&pre: (*a).m is well-defined. +Equivalent to (*a).m
+
+
+
+

Writable Iterators [lib.writable.iterators]

+

A class or built-in type X models the Writable Iterator concept +if the following expressions are valid and respect the stated +semantics.

+ +
+
+

Swappable Iterators [lib.swappable.iterators]

+

A class or built-in type X models the Swappable Iterator concept +if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + +
Swappable Iterator Requirements (in addition to CopyConstructible)
ExpressionReturn TypePostcondition
iter_swap(a, b)voidpost: the pointed to values are exchanged
+
+
+
[Note: An iterator that is a model of the Readable and Writable Iterator concepts
+
is also a model of Swappable Iterator. --end note]
+
+
+
+

Readable Lvalue Iterators [lib.readable.lvalue.iterators]

+

The Readable Lvalue Iterator concept adds the requirement that the +reference type be a reference to the value type of the iterator.

+
+ +++++ + + + + + + + + + + + + + + + + + + +
Readable Lvalue Iterator Requirements (in addition to Readable Iterator)
ExpressionReturn TypeAssertion
iterator_traits<X>::referenceT&T is cv +iterator_traits<X>::value_type +where cv is an optional +cv-qualification
access_category<X>::typeConvertible to +readable_lvalue_iterator_tag 
+
+
+
+

Writable Lvalue Iterators [lib.writable.lvalue.iterators]

+

The Writable Lvalue Iterator concept adds the requirement that the +reference type be a non-const reference to the value type of the +iterator.

+
+ ++++ + + + + + + + + + + + + + + + +
Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator)
ExpressionReturn Type
iterator_traits<X>::referenceiterator_traits<X>::value_type&
access_category<X>::typeConvertible to writable_lvalue_iterator_tag
+
+
+
+
+

Iterator Traversal Concepts [lib.iterator.traversal]

+

In the tables below, X is an iterator type, a and b are +constant objects of type X, r and s are mutable objects of +type X, T is std::iterator_traits<X>::value_type, and +v is a constant object of type T.

+
+

Incrementable Iterators [lib.incrementable.iterators]

+

A class or built-in type X models the Incrementable Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
ExpressionReturn TypeAssertion/Semantics
++rX&&r == &++r
r++X{ X tmp = r; ++r; return tmp; }
traversal_category<X>::typeConvertible to incrementable_iterator_tag 
+
+
+
+

Single Pass Iterators [lib.single.pass.iterators]

+

A class or built-in type X models the Single Pass Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable)
ExpressionReturn TypeAssertion/Semantics/Pre-/Post-condition
++rX&pre: r is dereferenceable; post: +r is dereferenceable or r is +past-the-end
a == bconvertible to bool== is an equivalence relation over +its domain
a != bconvertible to bool!(a == b)
traversal_category<X>::typeConvertible to +single_pass_iterator_tag 
+
+
+
+

Forward Traversal Iterators [lib.forward.traversal.iterators]

+

A class or built-in type X models the Forward Traversal Iterator +concept if the following expressions are valid and respect the stated +semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Forward Traversal Iterator Requirements (in addition to Single Pass Iterator)
ExpressionReturn TypeAssertion/Note
X u;X&note: u may have a +singular value.
++rX&r == s and r is +dereferenceable implies +++r == ++s.
iterator_traits<X>::difference_typeA signed integral type representing +the distance between iterators 
traversal_category<X>::typeConvertible to +forward_traversal_iterator_tag 
+
+
+
+

Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

+

A class or built-in type X models the Bidirectional Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator)
ExpressionReturn TypeAssertion/Semantics/Pre-/Post-condition
--rX&pre: there exists s such that r +== ++s. post: s is +dereferenceable. --(++r) == r. +--r == --s implies r == s. &r +== &--r.
r--convertible to const X&{ X tmp = r; --r; return tmp; }
traversal_category<X>::typeConvertible to +bidirectional_traversal_iterator_tag 
+
+
+
+

Random Access Traversal Iterators [lib.random.access.traversal.iterators]

+

A class or built-in type X models the Random Access Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics. In the table below, Distance is +iterator_traits<X>::difference_type and n represents a +constant object of type Distance.

+
+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator)
ExpressionReturn TypeOperational SemanticsAssertion/Precondition
r += nX&
+{
+  Distance m = n;
+  if (m >= 0)
+    while (m--)
+      ++r;
+  else
+    while (m++)
+      --r;
+  return r;
+}
+
+
 
a + n, n + aX{ X tmp = a; return +tmp += n; } 
r -= nX&return r += -n 
a - nX{ X tmp = a; return +tmp -= n; } 
b - aDistancea < b ? +distance(a,b) : +-distance(b,a)pre: there exists a value +n of Distance such +that a + n == b. b == +a + (b - a).
a[n]convertible to T*(a + n)pre: a is a readable +iterator
a[n] = vconvertible to T*(a + n) = vpre: a is a writable +iterator
a < bconvertible to boolb - a > 0< is a total ordering +relation
a > bconvertible to boolb < a> is a total ordering +relation
a >= bconvertible to bool!(a < b) 
a <= bconvertible to bool!(a > b) 
traversal_category<X>::typeConvertible to +random_access_traversal_iterator_tag  
+
+
+
+
+
+

Addition to [lib.iterator.synopsis]

+
+// lib.iterator.traits, traits and tags
+template <class Iterator> struct access_category;
+template <class Iterator> struct traversal_category;
+
+template <class AccessTag, class TraversalTag>
+struct iterator_tag : /* appropriate old category or categories */ {
+  typedef AccessTag access;
+  typedef TraversalTag traversal;
+};
+
+struct readable_iterator_tag { };
+struct writable_iterator_tag { };
+struct swappable_iterator_tag { };
+struct readable_writable_iterator_tag
+  : virtual readable_iterator_tag
+  , virtual writable_iterator_tag
+  , virtual swappable_iterator_tag { };
+struct readable_lvalue_iterator_tag { };
+struct writable_lvalue_iterator_tag
+  : virtual public readable_writable_iterator_tag
+  , virtual public readable_lvalue_iterator_tag { };
+
+struct incrementable_iterator_tag { };
+struct single_pass_iterator_tag : incrementable_iterator_tag { };
+struct forward_traversal_tag : single_pass_iterator_tag { };
+struct bidirectional_traversal_tag : forward_traversal_tag { };
+struct random_access_traversal_tag : bidirectional_traversal_tag { };
+
+struct null_category_tag { };
+struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};
+
+
+
+

Addition to [lib.iterator.traits]

+

The iterator_tag class template is an iterator category tag that +encodes the access and traversal tags in addition to being compatible +with the original iterator tags. The iterator_tag class inherits +from one of the original iterator tags according to the following +pseudo-code.

+
+inherit-category(access-tag, traversal-tag) =
+     if (access-tag is convertible to readable_lvalue_iterator_tag) {
+         if (traversal-tag is convertible to random_access_traversal_tag)
+             return random_access_iterator_tag;
+         else if (traversal-tag is convertible to bidirectional_traversal_tag)
+             return bidirectional_iterator_tag;
+         else if (traversal-tag is convertible to forward_traversal_tag)
+             return forward_iterator_tag;
+         else if (traversal-tag is convertible to single_pass_traversal_tag)
+             if (access-tag is convertible to writable_iterator_tag)
+                 return input_output_iterator_tag;
+             else
+                 return input_iterator_tag;
+         else if (access-tag is convertible to writable_iterator_tag)
+             return output_iterator_tag;
+         else
+             return null_category_tag;
+     } else if (access-tag is convertible to readable_writable_iterator_tag
+                and traversal-tag is convertible to single_pass_iterator_tag)
+         return input_output_iterator_tag;
+     else if (access-tag is convertible to readable_iterator_tag
+              and traversal-tag is convertible to single_pass_iterator_tag)
+         return input_iterator_tag;
+     else if (access-tag is convertible to writable_iterator_tag
+              and traversal-tag is convertible to incrementable_iterator_tag)
+         return output_iterator_tag;
+     else
+         return null_category_tag;
+
+

The access_category and traversal_category class templates are +traits classes. For iterators whose +iterator_traits<Iter>::iterator_category type is iterator_tag, +the access_category and traversal_category traits access the +access and traversal member types within iterator_tag. +For iterators whose iterator_traits<Iter>::iterator_category type +is not iterator_tag and instead is a tag convertible to one of the +original tags, the appropriate traversal and access tags is deduced. +The following pseudo-code describes the algorithm.

+
+access-category(Iterator) =
+    cat = iterator_traits<Iterator>::iterator_category;
+    if (cat == iterator_tag<Access,Traversal>)
+        return Access;
+    else if (cat is convertible to forward_iterator_tag) {
+        if (iterator_traits<Iterator>::reference is a const reference)
+            return readable_lvalue_iterator_tag;
+        else
+            return writable_lvalue_iterator_tag;
+    } else if (cat is convertible to input_iterator_tag)
+        return readable_iterator_tag;
+    else if (cat is convertible to output_iterator_tag)
+        return writable_iterator_tag;
+    else
+        return null_category_tag;
+
+traversal-category(Iterator) =
+    cat = iterator_traits<Iterator>::iterator_category;
+    if (cat == iterator_tag<Access,Traversal>)
+        return Traversal;
+    else if (cat is convertible to random_access_iterator_tag)
+        return random_access_traversal_tag;
+    else if (cat is convertible to bidirectional_iterator_tag)
+        return bidirectional_traversal_tag;
+    else if (cat is convertible to forward_iterator_tag)
+        return forward_traversal_tag;
+    else if (cat is convertible to input_iterator_tag)
+        return single_pass_iterator_tag;
+    else if (cat is convertible to output_iterator_tag)
+        return incrementable_iterator_tag;
+    else
+        return null_category_tag;
+
+

The following specializations provide the access and traversal +category tags for pointer types.

+
+template <typename T>
+struct access_category<const T*>
+{
+  typedef readable_lvalue_iterator_tag type;
+};
+template <typename T>
+struct access_category<T*>
+{
+  typedef writable_lvalue_iterator_tag type;
+};
+
+template <typename T>
+struct traversal_category<T*>
+{
+  typedef random_access_traversal_tag type;
+};
+
+ +
+
+
+ + + + diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst index 9005000..be1b357 100644 --- a/doc/new-iter-concepts.rst +++ b/doc/new-iter-concepts.rst @@ -6,7 +6,7 @@ :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de :organization: `Boost Consulting`_, Indiana University `Open Systems Lab`_, University of Hanover `Institute for Transport Railway Operation and Construction`_ :date: $Date$ -:Number: N1477=03-0060 +:Number: **This document is a revised version of the official** N1477=03-0060 :copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved .. _`Boost Consulting`: http://www.boost-consulting.com