From 80d9e8e4c1942fe810de1e772e6ca7aea680388e Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Mon, 7 Jul 2003 14:20:34 +0000 Subject: [PATCH] Move from boost-sandbox [SVN r18959] --- doc/access.png | Bin 0 -> 11127 bytes doc/access2old.png | Bin 0 -> 42175 bytes doc/default.css | 188 ++ doc/facade-and-adaptor.rst | 1598 +++++++++++++++++ doc/iterator-categories.html | 822 +++++++++ doc/new-iter-concepts.rst | 731 ++++++++ doc/oldeqnew.png | Bin 0 -> 33786 bytes doc/traversal.png | Bin 0 -> 9112 bytes example/Jamfile | 1 + example/reverse_iterator.cpp | 16 + include/boost/iterator/detail/categories.hpp | 338 ++++ include/boost/iterator/detail/config_def.hpp | 104 ++ .../boost/iterator/detail/config_undef.hpp | 26 + include/boost/iterator/detail/enable_if.hpp | 88 + 14 files changed, 3912 insertions(+) create mode 100644 doc/access.png create mode 100644 doc/access2old.png create mode 100644 doc/default.css create mode 100644 doc/facade-and-adaptor.rst create mode 100644 doc/iterator-categories.html create mode 100644 doc/new-iter-concepts.rst create mode 100644 doc/oldeqnew.png create mode 100644 doc/traversal.png create mode 100644 example/Jamfile create mode 100644 example/reverse_iterator.cpp create mode 100644 include/boost/iterator/detail/categories.hpp create mode 100644 include/boost/iterator/detail/config_def.hpp create mode 100644 include/boost/iterator/detail/config_undef.hpp create mode 100644 include/boost/iterator/detail/enable_if.hpp diff --git a/doc/access.png b/doc/access.png new file mode 100644 index 0000000000000000000000000000000000000000..80011dcc7c82a35cbc173b314a9e247db0bf3f8c GIT binary patch literal 11127 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 Ofx*+&&t;ucLK6UGF@%Z$ literal 0 HcmV?d00001 diff --git a/doc/default.css b/doc/default.css new file mode 100644 index 0000000..2e1fddb --- /dev/null +++ b/doc/default.css @@ -0,0 +1,188 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date$ +:version: $Revision$ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/doc/facade-and-adaptor.rst b/doc/facade-and-adaptor.rst new file mode 100644 index 0000000..169b856 --- /dev/null +++ b/doc/facade-and-adaptor.rst @@ -0,0 +1,1598 @@ ++++++++++++++++++++++++++++++ + 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: $Date$ +:Number: N1476=03-0059 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: We propose a set of class templates that help programmers + build standard-conforming iterators, both from scratch and + by adapting other iterators. + +.. contents:: 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 [#mutable]_, 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. + +.. [#concept] We use the term concept to mean a set of requirements + that a type must satisfy to be used with a particular template + parameter. + +.. [#mutable] 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. + +.. _`n1477`: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1477.html + +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. + +.. _`179`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#179 +.. _`280`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280 + + +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. The policy object approach does not allow for custom constructors + on the created iterator types, an essential feature if + ``iterator_facade`` should be used in other library + implementations. + + 3. Without the use of CRTP, the standard requirement that an + iterator's ``operator++`` returns the iterator type itself 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. + +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 +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`_. + + +----------------------------------------+-------------------------------------------+ + | 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? + +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. Also, if the iterator is to model Forward Traversal +Iterator, 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. + +.. This is no long uptodate -thw +.. Yes it is; I made sure of it! -DWA + +``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. + +.. _issue 299: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299 + +``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`` [#base]_ +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. + +.. [#base] 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 +assumtion. + +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: + +* ``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 ```` 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 reverse_iterator; + + template < + class UnaryFunction + , class Iterator + , class Reference = use_default + , class Value = use_default + > + class transform_iterator; + + template + class filter_iterator; + + template < + class Incrementable + , class Category = use_default + , class Difference = use_default + > + class counting_iterator + + template + 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::type value_type; + typedef Reference reference; + 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; + 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 + typename enable_if_interoperable::type // exposition + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator difference + template + typename enable_if_interoperable::type + operator -(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator addition + template + Derived operator+ (iterator_facade 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.] + + +.. we need a new label here because the presence of markup in the + title prevents an automatic link from being generated + +.. _iterator facade requirements: + +``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``. + ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ +| 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``. | | ++----------------------------------------+----------------------------------------+-------------------------------------------------+-------------------------------------------+ + + +.. We should explain more about how the + functions in the interface of iterator_facade + are there conditionally. -JGS + + +``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(this)->dereference()`` + +*see below* ``operator->() const;`` + +:Returns: If ``X::reference`` is a reference type, returns an object + of type ``X::pointer`` equal to:: + + &static_cast(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(this)->increment(); + return *this; + +.. I realize that the committee is moving away from specifying things + like this in terms of code, but I worried about the imprecision of + saying that a core interface function is invoked without describing + the downcast. An alternative to what I did would be to mention it + above where we talk about accessibility. + + +``Derived operator++(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + ++*this; + return tmp; + + +``Derived& operator--();`` + +:Effects: + + :: + + static_cast(this)->decrement(); + return *this; + + +``Derived operator--(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + --*this; + return tmp; + + +``Derived& operator+=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(n); + return *this; + + +``Derived& operator-=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(-n); + return *this; + + +``Derived operator-(difference_type n) const;`` + +:Effects: + + Derived tmp(static_cast(this)); + return tmp -= n; + +:Returns: ``static_cast(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 + { + 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 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 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::value_type; + else + value_type = remove_cv::type; + + if (Reference == use_default) { + if (Value == use_default) + reference = iterator_traits::reference; + else + reference = Value&; + } else + reference = Reference; + + if (Distance == use_default) + difference_type = iterator_traits::difference_type; + else + difference_type = Distance; + + if (Category == use_default) + iterator_category = iterator_tag< + access_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > >, + traversal_category< + iterator< iterator_traits::iterator_category, + Value, + Distance, + Value*, + Reference > > + else + iterator_category = Category; + + +.. Replaced with new semantics --thw + if (Category == use_default) + iterator_category = iterator_traits::iterator_category; + 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 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 const& y) const; + +:Returns: ``y.base() - m_iterator`` + + + +Specialized adaptors [lib.iterator.special.adaptors] +==================================================== + +.. The requirements for all of these need to be written *much* more + formally -DWA + + +[*Note:* The ``enable_if_convertible::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``) as if it were a container of the pointed-to type +(e.g. ``list``) . + +.. At some point we should add the capability to handle + iterators over smart pointers, which the impl handles. -JGS + + +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 + { + 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::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::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_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::type* = 0 // exposition + ); + +:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. +:Returns: An instance of ``indirect_iterator`` that is a copy of ``y``. + +Reverse iterator +---------------- + +.. I think we'd better strike the old reverse_iterator text from the standard, eh? + +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 reverse_iterator : + public iterator_adaptor< reverse_iterator, Iterator > + { + friend class iterator_core_access; + public: + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::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 + typename reverse_iterator::difference_type + distance_to(reverse_iterator 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 + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::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 transform_iterator + : public iterator_adaptor + { + friend class iterator_core_access; + public: + transform_iterator(); + transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::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::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 + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::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 filter_iterator + : public iterator_adaptor< + filter_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 + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::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``. + +.. Thomas is going to try implementing filter_iterator so that + it will be bidirectional if the underlying iterator is. -JGS + + +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::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 + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::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 counting_iterator + : public iterator_adaptor< + counting_iterator + , 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 function_output_iterator { + public: + typedef iterator_tag< + writable_iterator_tag + , incrementable_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()); + + struct output_proxy { + output_proxy(UnaryFunction& f); + template 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 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. + +.. + LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate + LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv + LocalWords: GraphBase struct ptrdiff UnaryFunction const int typename bool pp + LocalWords: lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo + LocalWords: dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd + LocalWords: OtherIncrementable Coplien diff --git a/doc/iterator-categories.html b/doc/iterator-categories.html new file mode 100644 index 0000000..eb76523 --- /dev/null +++ b/doc/iterator-categories.html @@ -0,0 +1,822 @@ + +Improved Iterator Categories and Requirements + + + +

+
Improved Iterator Categories and Requirements

+

Introduction

The standard iterator categories and requirements are +flawed because they use a single hierarchy of requirements to address two +orthogonal issues: iterator traversal and dereference return +type. The current iterator requirement hierarchy is mainly geared +towards iterator traversal (hence the category names), while requirements that +address dereference return type sneak in at various places. The following table +gives a summary of the current dereference return type 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 (which is odd because the + operational semantics say i[n] is equivalent to *(i + n) + which would have a return type of T&)
Table 1. Summary of current dereference return type + requirements.
+

Examples of useful iterators that do not ``fit''

+

Because of the mixing of iterator traversal and dereference return type, 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 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. Also, +vector<bool> is not the only example of useful iterators that do +not return true references: there is the often cited example of disk-based +collections. +

Another example is a counting iterator, an iterator the returns a sequence of +integers when incremented and dereferenced (see boost::counting_iterator). +There are two ways to implement this iterator, 1) make the reference +type be a true reference (a reference to an integer data member of the counting +iterator) or 2) make the reference type be the same as the +value_type. Option 1) runs into the problems discussed in Issue +198, the reference will not be valid after the iterator is destroyed. Option +2) is therefore a better choice, but then we have a counting iterator that +cannot be a random access iterator. +

Yet another example is a transform iterator, an iterator adaptor that applies +a unary function object to the dereference value of the wrapped iterator (see boost::transform_iterator). +For unary functions such as std::times the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. However, with the current iterator +requirements, if you wrap int* with a transform iterator, you do not +get a random access iterator as expected, but an input iterator. +

A fourth 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 +std::input_iterator_tag, which means that, strictly speaking, you could +not use these iterators with algorithms like std::min_element(). As a +temporary solution, we introduced the concept Multi-Pass +Input Iterator to describe the vertex and edge descriptors, but as the +design notes for 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 miss-categorized. +
  • Algorithm requirements are more strict than necessary, because they can + not separate out the need for random-access from the need for a true reference + return type.
+

Proposal for new iterator categories and requirements

The iterator +requirements should be separated into two hierarchies. One set of concepts +handles the return type semantics: +The other set of concepts handles iterator +traversal: + + +

The current Input Iterator and Output Iterator requirements will +continue to be used as is. Note that Input Iterator implies Readable +Iterator and Output Iterator implies Writable Iterator.

+ +

Note: we considered defining a Single-Pass Iterator, which could be +combined with Readable or Writable Iterator to replace the Input and +Output Iterator requirements. We rejected this idea because there are +several differences between Input and Output Iterators that make it +hard to merge them: Input Iterator requires Equality Comparable while +Output Iterator does not and Input Iterator requires Assignable while +Output Iterator does not.

+ +

New category tags and traits classes

+ +

The new iterator categories will require new tag classes.

+ +
namespace std {
+
+  // Returns Category Tags
+  struct readable_iterator_tag { };
+  struct writable_iterator_tag { };
+  struct swappable_iterator_tag { };
+  struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag,
+    virtual public readable_iterator_tag { };
+  struct constant_lvalue_iterator_tag : public readable_iterator_tag { };
+
+  // Traversal Category Tags
+  struct input_traversal_tag { };
+  struct output_traversal_tag { };
+  struct forward_traversal_tag { };
+  struct bidirectional_traversal_tag : public forward_traversal_tag { };
+  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
+
+}
+
+ +

Access to the return and traversal tags will be through the +following two traits classes, which have a member typedef named +type that provides the tag type. We explain the +definitions of these classes later.

+ +
+  template <typename Iterator>
+  struct return_category; // contains: typedef ... type;
+
+  template <typename Iterator>
+  struct traversal_category; // contains: typedef ... type;
+
+ +

We want it to be convenient for programmers to create iterators +that satisfy both the old and new iterator requirements. Therefore +the following class is provided as a way to create tags for use as the +old iterator_category typedef within +iterator_traits. + +

namespace std {
+  template <class ReturnTag, class TraversalTag>
+  struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
+  {
+    typedef ReturnTag returns;
+    typedef TraversalTag traversal;
+  };
+
+ +

The cvt_iterator_category template computes the +appropriate old iterator category based on the return and traversal +category.

+ +
namespace std {
+  template <class RC, class TC>
+  struct cvt_iterator_category
+  {
+    // Pseudo-code, <= means inherits or same type
+    if (RC <= constant_lvalue_iterator_tag || RC <= mutable_lvalue_iterator_tag) {
+      if (TC <= random_access_traversal_tag)
+        typedef random_access_iterator_tag type;
+      else if (TC <= bidirectional_traversal_tag)
+        typedef bidirectional_iterator_tag type;
+      else if (TC <= forward_traversal_tag)
+        typedef forward_iterator_tag type;
+      else
+        error;
+   } else if (RC <= readable_iterator_tag && RC <= input_traversal_tag)
+     typedef input_iterator_tag type;
+   else if (RC <= writable_iterator_tag && output_traversal_tag)
+     typedef output_iterator_tag type;
+   else
+     error;
+  };
+}
+
+ +

The following is an example of a new iterator class using the +iterator_tag class to create its iterator_category +member typedef.

+ +
+struct my_iterator {
+  typedef std::iterator_tag<std::readable_iterator_tag, 
+    std::random_access_traversal_tag> iterator_category;
+  ...
+};
+
+ +We also want old iterators to work with new algorithms, that is, +algorithms that use the new iterator categories. We facilitate this by +defining the return_category and traversal_category +in such a way as they can be used with both old and new iterators. +For old iterators, the appropriate return and traversal categories are +computed based on the old iterator category. For new iterators, the +return and traversal tags are extracted from within the +iterator_category tag. + + +
+  template <typename Iterator>
+  class return_category
+  {
+    // Pseudo-code
+    typedef iterator_traits<Iterator>::iterator_category tag;
+    typedef iterator_traits<Iterator>::value_type T;
+  public:
+    if (exists(tag::returns)) // must be a new iterator
+      typedef tag::returns type;
+    else if (tag <= forward_iterator_tag) {
+      if (is-const(T))
+        typedef constant_lvalue_iterator_tag type;
+      else
+        typedef mutable_lvalue_iterator_tag type;
+    } else if (tag <= input_iterator_tag)
+      typedef readable_iterator_tag type;
+    else if (tag <= output_iterator_tag)
+      typedef writable_iterator_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct return_category<T*>
+  {
+    // Pseudo-code
+    if (is-const(T))
+      typedef boost::constant_lvalue_iterator_tag type;
+    else
+      typedef boost::mutable_lvalue_iterator_tag type;
+  };
+
+  template <typename Iterator>
+  class traversal_category
+  {
+    typedef iterator_traits<Iterator>::iterator_category tag;
+  public:
+    // Pseudo-code
+    if (exists(tag::traversal)) // must be a new iterator
+      typedef tag::traversal type;
+    else if (tag <= random_access_iterator_tag)
+      typedef random_access_traversal_tag type;
+    else if (tag <= bidirectional_iterator_tag)
+      typedef bidirectional_traversal_tag type;
+    else if (tag <= is_forward_iterator_tag)
+      typedef forward_traversal_tag type;
+    else if (tag <= input_iterator_tag)
+      typedef input_traversal_tag type;
+    else if (tag <= out_iterator_tag)
+      typedef output_traversal_tag type;
+    else
+      error;
+  };
+
+  template <typename T>
+  struct traversal_category<T*>
+  {
+    typedef random_access_traversal_tag type;
+  };
+
+ +

Impact on the Standard Algorithms

+ +

Many of the standard algorithms place more requirements than +necessary on their iterator parameters due to the coarseness of the +current iterator categories. By using the new iterator categories a +better fit can be achieved, thereby increasing the reusability of the +algorithms. These changes will not affect user-code, though they will +require changes by standard implementers: dispatching should be based +on the new categories, and in places return values may need to be +handled more carefully. In particular, uses of std::swap() +will need to be replaced with std::iter_swap(), and +std::iter_swap() will need to call std::swap().

+ +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlgorithmRequirement Change
find_endForward Iterator
-> Forward Traversal Iterator and + Readable Iterator
find_first_of
adjacent_find
search
search_n
rotate_copy
lower_bound
upper_bound
equal_range
binary_search
min_element
max_element
iter_swapForward Iterator
-> Swappable Iterator
fillForward Iterator
-> Forward Traversal Iterator and + Writable Iterator
generate
swap_rangesForward Iterator
-> Forward Traversal Iterator and + Swappable Iterator
rotate
replaceForward Iterator
-> Forward Traversal Iterator + and
Readable Iterator and Writable Iterator
replace_if
remove
remove_if
unique
reverseBidirectional Iterator
-> Bidirectional Traversal + Iterator and Swappable Iterator
partition
copy_backwardsBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
Bidirectional Iterator
-> Bidirectional + Traversal Iterator and Writable Iterator
next_permutationBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Swappable Iterator and Readable Iterator
prev_permutation
stable_partitionBidirectional Iterator
-> Bidirectional Traversal + Iterator and
Readable Iterator and Writable Iterator
inplace_merge
reverse_copyBidirectional Iterator
-> Bidirectional Traversal Iterator and + Readable Iterator
random_shuffleRandom Access Iterator
-> Random Access Traversal + Iterator and Swappable Iterator
sort
stable_sort
partial_sort
nth_element
push_heap
pop_heap
make_heap
sort_heap
Table 2. Requirement changes for standard + algorithms.
+

The New Iterator Requirements

+

Notation

+ + + + + + + + + + + + + +
XThe iterator type.
TThe value type of X, i.e., + std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.
+

+


+ +

Readable Iterator

A Readable +Iterator is an iterator that dereferences to produce an rvalue that is +convertible to the value_type of the iterator. +

Associated Types

+ + + + + + + + + + + + + +
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator. This type must be + convertible to T.
Return Categorystd::return_category<X>::typeA type convertible to std::readable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m.If m is a data member, the type of m. If m + is a member function, the return type of m.
+

+


+ +

Writable Iterator

A Writable +Iterator is an iterator that can be used to store a value using the +dereference-assignment expression. +

Definitions

If x is an Writable Iterator of type X, +then the expression *x = a; stores the value a into +x. Note that operator=, like other C++ functions, may be +overloaded; it may, in fact, even be a template function. In general, then, +a may be any of several different types. A type A belongs to +the set of value types of X if, for an object a of type +A, *x = a; is well-defined and does not require performing any +non-trivial conversions on a. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::writable_iterator_tag +
+

Refinement of

Copy +Constructible +

Valid expressions

+ + + + + + + + + +
NameExpressionReturn type
Dereference assignment*x = aunspecified
+

+


+ +

Swappable Iterator

A Swappable +Iterator is an iterator whose dereferenced values can be swapped. +

Note: the requirements for Swappable Iterator are dependent on the issues +surrounding std::swap() being resolved. Here we assume that the issue +will be resolved by allowing the overload of std::swap() for +user-defined types. +

Note: Readable Iterator and Writable Iterator combined implies Swappable +Iterator because of the fully templated std::swap(). However, Swappable +Iterator does not imply Readable Iterator nor Writable Iterator. +

Associated Types

+ + + + + +
Return Categorystd::return_category<X>::typeA type convertible to std::swappable_iterator_tag +
+

Valid expressions

Of the two valid expressions listed below, only one +OR the other is required. If std::iter_swap() is overloaded for +X then std::swap() is not required. If +std::iter_swap() is not overloaded for X then the default +(fully templated) version is used, which will call std::swap() (this +means changing the current requirements for std::iter_swap()). +

+ + + + + + + + + + + + + +
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
+

+


+ +

Constant Lvalue Iterator

A +Constant Lvalue Iterator is an iterator that dereferences to produce a const +reference to the pointed-to object, i.e., the associated reference type +is const T&. Changing the value of or destroying an iterator that +models Constant Lvalue Iterator does not invalidate pointers and references +previously obtained from that iterator. +

Refinement of

Readable +Iterator +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be const + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::constant_lvalue_iterator_tag +
+

+


+ +

Mutable Lvalue Iterator

A +Mutable Lvalue Iterator is an iterator that dereferences to produce a reference +to the pointed-to object. The associated reference type is +T&. Changing the value of or destroying an iterator that models +Mutable Lvalue Iterator does not invalidate pointers and references previously +obtained from that iterator. +

Refinement of

Readable +Iterator, Writable +Iterator, and Swappable +Iterator. +

Associated Types

+ + + + + + + + + +
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be + T&.
Return Categorystd::return_category<X>::typeA type convertible to std::mutable_lvalue_iterator_tag +
+

+


+ +

Forward Traversal Iterator +

The Forward Iterator is an iterator that can be incremented. Also, it is +permissible to make multiple passes through the iterator's range. +

Refinement of

Copy +Constructible, Assignable, Default +Constructible, and Equality +Comparable +

Associated types

+ + + + + + + + + +
Difference Typestd::iterator_traits<X>::difference_typeA signed integral type used for representing distances between + iterators that point into the same range.
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::forward_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrementi++ convertible to const X&
+

+


+ +

Bidirectional Traversal +Iterator

An iterator that can be incremented and decremented. +

Refinement of

Forward +Traversal Iterator +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::bidirectional_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- convertible to const X&
+

+


+ +

Random Access Traversal +Iterator

An iterator that provides constant-time methods for moving forward +and backward in arbitrary-sized steps. +

Refinement of

Bidirectional +Traversal Iterator and Less Than +Comparable where < is a total ordering +

Associated types

+ + + + + +
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::random_access_traversal_tag +
+

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of Readable + Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of Writable + Iterator.unspecified
+

+


+ diff --git a/doc/new-iter-concepts.rst b/doc/new-iter-concepts.rst new file mode 100644 index 0000000..cd29dbe --- /dev/null +++ b/doc/new-iter-concepts.rst @@ -0,0 +1,731 @@ +++++++++++++++++++++++ + 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: $Date$ +:Number: N1477=03-0060 +:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +: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_. + +.. contents:: Table of Contents + +.. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html + +============ + 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 Iterator | ``i[n]`` is convertible to ``T`` (also ``i[n] = t`` is required for | +| | mutable iterators once `issue 299`_ is resolved) | ++------------------------+-------------------------------------------------------------------------+ + +.. _issue 200: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200 +.. _issue 299: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#299 + + +Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, ``vector::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`` 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``. + +.. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96 + +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. + +.. _`transform_iterator`: http://www.boost.org/libs/utility/transform_iterator.htm + +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. + +.. _Boost Graph Library: http://www.boost.org/libs/graph/doc/table_of_contents.html +.. _Multi-Pass Input Iterator: http://www.boost.org/libs/utility/MultiPassInputIterator.html + +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. + +.. I think we need to say something about the resolution to allow + convertibility to any of the old-style tags as a TR issue (hope it + made it). -DWA + +.. Hmm, not sure I understand. Are you talking about whether a + standards conforming input iterator is allowed to have + a tag that is not input_iterator_tag but that + is convertible to input_iterator_tag? -JGS + +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. + +.. image:: 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. + +.. image:: 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. + +.. image:: 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::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 + 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 struct access_category { typedef ... type; }; + template 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::value_type``, and ``v`` is a constant +object of type ``T``. + +.. _Readable Iterator: + +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) | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+===================================================+=================================================================+ + | ``iterator_traits::value_type`` | ``T`` | Any non-reference, non-cv-qualified type | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``iterator_traits::reference`` | Convertible to ``iterator_traits::value_type`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``access_category::type`` | Convertible to ``readable_iterator_tag`` | | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``*a`` | ``iterator_traits::reference`` | pre: ``a`` is dereferenceable. If ``a == b`` then | + | | | ``*a`` is equivalent to ``*b`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + | ``a->m`` | ``U&`` | pre: ``(*a).m`` is well-defined. Equivalent to ``(*a).m`` | + +--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+ + + +.. _Writable Iterator: + +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. + +.. A type ``T`` belongs to the *set of value types* of ``X`` + if, for an object ``v`` of type ``T``, ``*a = v`` is valid. + + ** This appears to be a mutual recursion which ends up meaning + nothing. Kill the assertion column? + + Separate but related question: Is a writable iterator required + to have a meaningful value_type? If not, we need to use a + different name from ``v`` in this table -DWA + ++------------------------------------------------------------------------------------------------------------------------------+ +| Writable Iterator Requirements (in addition to CopyConstructible) | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| Expression | Return Type | Assertion/Note/Precondition/Postcondition | ++======================================+==========================================+============================================+ +| ``access_category::type`` | Convertible to ``writable_iterator_tag`` | | ++--------------------------------------+------------------------------------------+--------------------------------------------+ +| ``*a = v`` | | .. ** pre: The type of ``v`` is in the set | +| | | of value types of ``X`` | ++--------------------------------------+------------------------------------------+--------------------------------------------+ + + +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) | + +------------------------------------+-------------+---------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=============+=============================================+ + | ``iter_swap(a, b)`` | ``void`` | post: 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) | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +====================================+=================================================+===========================================================+ + | ``iterator_traits::reference`` | ``T&`` | ``T`` is *cv* ``iterator_traits::value_type`` where | + | | | *cv* is an optional cv-qualification | + +------------------------------------+-------------------------------------------------+-----------------------------------------------------------+ + | ``access_category::type`` | Convertible 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) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``iterator_traits::reference`` | ``iterator_traits::value_type&`` | | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``access_category::type`` | Convertible 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::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) | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition | + +======================================+==================================================+============================================================+ + | ``++r`` | ``X&`` | ``&r == &++r`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` | + +--------------------------------------+--------------------------------------------------+------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible 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) | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==================================+=========================+=========================================================================================+ + | ``++r`` | ``X&`` | pre: ``r`` is dereferenceable; post: ``r`` is dereferenceable or ``r`` is past-the-end | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a == b`` | convertible to ``bool`` | ``==`` is an equivalence relation over its domain | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``a != b`` | convertible to ``bool`` | ``!(a == b)`` | + +----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible 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) | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +==========================================+==============+========================================================================+ + | ``X u;`` | ``X&`` | ``note: u may have a singular value.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``++r`` | ``X&`` | ``r == s`` and ``r`` is dereferenceable implies ``++r == ++s.`` | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``iterator_traits::difference_type`` | | A signed integral type representing the distance between iterators | + +------------------------------------------+--------------+------------------------------------------------------------------------+ + | ``traversal_category::type`` | | Convertible 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) | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | Expression | Return Type | Assertion/Note/Precondition/Postcondition/Semantics | + +=========================================+=============+=====================================================+ + | ``--r`` | ``X&`` |pre: there exists ``s`` such that ``r == ++s``. | + | | |post: ``s`` is dereferenceable. ``--(++r) == r``. | + | | |``--r == --s`` implies ``r == s``. ``&r == &--r``. | + +-----------------------------------------+-------------+-----------------------------------------------------+ + |``r--`` |convertible |``{ X tmp = r; --r; return tmp; }`` | + | |to ``const | | + | |X&`` | | + +-----------------------------------------+-------------+-----------------------------------------------------+ + | ``traversal_category::type`` | | Convertible 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::difference_type`` and ``n`` represents a +constant object of type ``Distance``. + + +--------------------------------------------------------------------------------------------------------------------------------------------+ + | Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | Expression | Return Type | Operational Semantics | Assertion/Note/Pre/Post-condition | + +================================+=======================================+==========================+========================================+ + |``r += n`` | ``X&`` |:: | | + | | | | | + | | | { | | + | | | Distance m = n; | | + | | | if (m >= 0) | | + | | | while (m--) | | + | | | ++r; | | + | | | else | | + | | | while (m++) | | + | | | --r; | | + | | | return r; | | + | | | } | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + | ``a + n``, ``n + a`` | ``X`` |``{ X tmp = a; return tmp | | + | | |+= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``r -= n`` | ``X&`` |``return r += -n`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a - n`` | ``X`` |``{ X tmp = a; return tmp | | + | | |-= n; }`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``b - a`` |``Distance`` |``a < b ? distance(a,b) : |pre: there exists a value ``n`` of | + | | |-distance(b,a)`` |``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] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `writable iterator`_ | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total ordering relation | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + |``traversal_category::type`` | | |Convertible to | + | | | |``random_access_traversal_iterator_tag``| + +--------------------------------+---------------------------------------+--------------------------+----------------------------------------+ + + + +Addition to [lib.iterator.synopsis] +=================================== + +:: + + // lib.iterator.traits, traits and tags + template struct access_category; + template struct traversal_category; + + template + 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::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::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_category; + if (cat == iterator_tag) + return Access; + else if (cat is convertible to forward_iterator_tag) { + if (iterator_traits::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_category; + if (cat == iterator_tag) + 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 + struct access_category + { + typedef readable_lvalue_iterator_tag type; + }; + template + struct access_category + { + typedef writable_lvalue_iterator_tag type; + }; + + template + struct traversal_category + { + typedef random_access_traversal_tag type; + }; + + + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS diff --git a/doc/oldeqnew.png b/doc/oldeqnew.png new file mode 100644 index 0000000000000000000000000000000000000000..30cd1598cb0b5f4cc54a8c600b7d55de7de270d5 GIT binary patch literal 33786 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../../.. $(BOOST) ; \ No newline at end of file diff --git a/example/reverse_iterator.cpp b/example/reverse_iterator.cpp new file mode 100644 index 0000000..ffe6e3d --- /dev/null +++ b/example/reverse_iterator.cpp @@ -0,0 +1,16 @@ +#include +#include +#include +#include +#include + +int main() +{ + int x[] = { 1, 2, 3, 4 }; + boost::reverse_iterator + , std::ptrdiff_t> first(x + 4), last(x); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + return 0; +} diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp new file mode 100644 index 0000000..48d1e3d --- /dev/null +++ b/include/boost/iterator/detail/categories.hpp @@ -0,0 +1,338 @@ +// (C) Copyright Thomas Witt 2002. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP +# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP + +# include +# include + +# include + +# include +# include + +# include +# include +# include +# include +# include +# include + +# include + +namespace boost +{ + + // faked new old-style categories needed to make new->old mapping + // work + namespace detail + { + struct null_category_tag {}; + struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {}; + } + + // + // Access Categories + // + struct readable_iterator_tag + { + typedef std::input_iterator_tag max_category; + }; + + struct writable_iterator_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct swappable_iterator_tag + { + typedef detail::null_category_tag max_category; + }; + + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + // + // Traversal Categories + // + struct incrementable_traversal_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct single_pass_traversal_tag + : incrementable_traversal_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct forward_traversal_tag + : single_pass_traversal_tag + { + typedef std::forward_iterator_tag max_category; + }; + + struct bidirectional_traversal_tag + : forward_traversal_tag + { + typedef std::bidirectional_iterator_tag max_category; + }; + + struct random_access_traversal_tag + : bidirectional_traversal_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct error_iterator_tag { }; + + namespace detail + { + // + // Tag detection meta functions + // + + // I bet this is defined somewhere else. Let's wait and see. + struct error_type; + +# ifndef BOOST_NO_IS_CONVERTIBLE + + // True iff T is a tag "derived" from Tag + template + struct is_tag + : mpl::or_< + is_convertible + + // Because we can't actually get forward_iterator_tag to + // derive from input_output_iterator_tag, we need this + // case. + , mpl::and_< + is_convertible + , is_convertible + > + > + {}; + + +# else + template + struct is_tag; +# endif + + // Generate specializations which will allow us to find + // null_category_tag as a minimum old-style category for new-style + // iterators which don't have an actual old-style category. We + // need that so there is a valid base class for all new-style + // iterators. +# define BOOST_OLD_ITERATOR_CATEGORY(category) \ + template <> \ + struct is_tag \ + : mpl::true_ {}; + + BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag) +# undef BOOST_OLD_ITERATOR_CATEGORY + + template <> + struct is_tag + : mpl::true_ + { + }; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_tag : mpl::true_ + {}; + +# ifdef BOOST_NO_IS_CONVERTIBLE + // Workarounds for CWPro7 which can't detect derivation at + // compile-time. + + // Fact of life: we can only detect tag refinement relationships + // among predefined tags. + // + // Algorithm: + // is_tag(T,U) -> + // T == U + // || (exists d in derived_from(T) such that is_tag(d, U)) + // + // T == U case is handled above + + // false by default + template + struct is_tag_impl : mpl::false_ + {}; + + // The generalized template dispatches to is_tag_impl because + // is_tag and is_tag are equally specialized. + // This technique simulates making is_tag more-specialized. + template + struct is_tag + : is_tag_impl + {}; + +# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \ + BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived) + +# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \ + template \ + struct is_tag_impl \ + : is_tag \ + { \ + }; + + // Old-style tag relations + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator) + + // Access tag relations + BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator) + BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator) + BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator) + + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator) + + // Traversal tag relations + BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal) + BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal) + BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal) + BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal) + +# endif // BOOST_NO_IS_CONVERTIBLE workarounds + +# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct known_tag + : mpl::apply_if, mpl::identity, Else> + {}; + + template + struct max_known_traversal_tag + : known_tag< + Tag, random_access_traversal_tag + , known_tag< + Tag, bidirectional_traversal_tag + , known_tag< + Tag, forward_traversal_tag + , known_tag< + Tag, single_pass_traversal_tag + , known_tag< + Tag, incrementable_traversal_tag + , error_iterator_tag + > + > + > + > + > + {}; + + // Doesn't cope with these odd combinations: readable+swappable, + // writable+swappable. That doesn't matter for the sake of + // new-style tag base computation, which is all it's used for + // anyway. + template + struct max_known_access_tag + : known_tag< + Tag, writable_lvalue_iterator_tag + , known_tag< + Tag, readable_lvalue_iterator_tag + , known_tag< + Tag, readable_writable_iterator_tag + , known_tag< + Tag, writable_iterator_tag + , known_tag< + Tag, readable_iterator_tag + , mpl::apply_if< + is_tag + , mpl::identity + , error_iterator_tag + > + > + > + > + > + > + {}; + + // + // Returns the minimum category type or error_type + // if T1 and T2 are unrelated. + // + // For compilers not supporting is_convertible this only + // works with the new boost return and traversal category + // types. The exact boost _types_ are required. No derived types + // will work. + // + // + template + struct minimum_category + : mpl::apply_if< + is_tag + , mpl::identity + , mpl::if_< + is_tag + , T2 + , error_type + > + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct minimum_category { typedef minimum_category type; }; +# endif + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP diff --git a/include/boost/iterator/detail/config_def.hpp b/include/boost/iterator/detail/config_def.hpp new file mode 100644 index 0000000..6789d4a --- /dev/null +++ b/include/boost/iterator/detail/config_def.hpp @@ -0,0 +1,104 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#include // for prior +#include + +#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x3000) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented" + +# if 0 // test code + template + struct bar + { + typedef int type; + }; + + template <> + struct bar + { + }; + + + template + struct foo : bar<(sizeof(T) == 1)> + { + }; + + template + char* f(int, typename foo::type = 0) { return 0; } + + template + int f(...) { return 0; } + + char* x = f(0); + int y = f(0); + + int main() + { + return 0; + } +# endif + +#endif + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types" +#endif + +#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile: + +# if 0 // test code + template + struct foo + { + foo(T); + + template + foo(foo const& other) : p(other.p) { } + + T p; + }; + + bool x = boost::is_convertible, foo >::value; +# endif + +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_ITERATOR_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work" +#endif + +#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE) +# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +// no include guard multiple inclusion intended diff --git a/include/boost/iterator/detail/config_undef.hpp b/include/boost/iterator/detail/config_undef.hpp new file mode 100644 index 0000000..f58df62 --- /dev/null +++ b/include/boost/iterator/detail/config_undef.hpp @@ -0,0 +1,26 @@ +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#undef BOOST_NO_SFINAE +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE +#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#undef BOOST_ARG_DEPENDENT_TYPENAME + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# undef BOOST_ITERATOR_CONFIG_DEF +#else +# error missing or nested #include config_def +#endif diff --git a/include/boost/iterator/detail/enable_if.hpp b/include/boost/iterator/detail/enable_if.hpp new file mode 100644 index 0000000..d939fbb --- /dev/null +++ b/include/boost/iterator/detail/enable_if.hpp @@ -0,0 +1,88 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +#ifndef BOOST_ENABLE_IF_23022003THW_HPP +#define BOOST_ENABLE_IF_23022003THW_HPP + +#include +#include + +#include + +// +// Boost iterators uses its own enable_if cause we need +// special semantics for deficient compilers. +// 23/02/03 thw +// + +namespace boost +{ + + namespace detail + { + // + // Base machinery for all kinds of enable if + // + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + // + // For compilers that don't support "Substitution Failure Is Not An Error" + // enable_if falls back to always enabled. See comments + // on operator implementation for consequences. + // + template<> + struct enabled + { + template + struct base + { +#ifdef BOOST_NO_SFINAE + + typedef T type; + + // This way to do it would give a nice error message containing + // invalid overload, but has the big disadvantage that + // there is no reference to user code in the error message. + // + // struct invalid_overload; + // typedef invalid_overload type; + // +#endif + }; + }; + + + template + struct enable_if +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled<(Cond::value)>::template base +# else + : mpl::identity +# endif + { +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + typedef Return type; +# endif + }; + + } // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ENABLE_IF_23022003THW_HPP