mirror of
https://github.com/boostorg/iterator.git
synced 2026-05-04 11:54:15 +02:00
9189d5bd60
[SVN r1228]
1517 lines
53 KiB
ReStructuredText
Executable File
1517 lines
53 KiB
ReStructuredText
Executable File
+++++++++++++++++++++++++++++
|
|
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 behaviour 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 categorisation 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 adressed 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``, ``pointer``, ``difference_type``, and
|
|
``iterator_category``.
|
|
|
|
Iterator facade uses the Curiously Recurring Template Pattern (CRTP)
|
|
[Cop95]_ so that the user can specifiy the behaviour of
|
|
``iterator_facade`` in a derived class. Former designs used policy
|
|
objects to specifiy the behaviour. 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?
|
|
|
|
.. Would this be a good place to talk about constructors? -JGS
|
|
|
|
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 funtions public would expose an implementation detail to
|
|
the user. This proposal frees the public interface of the derived
|
|
iterator type from any implementation detail.
|
|
|
|
Preventing direct access to the core member functions has two
|
|
advantages. First, there is no possibility for the user to accidently
|
|
use a member function of the iterator when a member of the value_type
|
|
was intended. This has been an issue with smart pointer
|
|
implementations in the past. The second and main advantage is that
|
|
library implementers can freely exchange a hand-rolled iterator
|
|
implementation for one based on ``iterator_facade`` without fear of
|
|
breaking code that was accessing the public core member functions
|
|
directly.
|
|
|
|
In a naive implementation, keeping the derived class' core member
|
|
functions private would require it to grant friendship to
|
|
``iterator_facade`` and each of the seven operators. In order to
|
|
reduce the burden of limiting access, this proposal provides
|
|
``iterator_core_access``, a class that acts as a gateway to the core
|
|
member functions in the derived iterator class. The author of the
|
|
derived class only needs to grant friendship to
|
|
``iterator_core_access`` to make his core member functions available
|
|
to the library.
|
|
|
|
``iterator_core_access`` will be typically implemented as an empty
|
|
class containing only private static member functions which invoke the
|
|
iterator core member functions. There is, however, no need to
|
|
standardize the gateway protocol. Note that even if
|
|
``iterator_core_access`` used public member functions it would not
|
|
open a safety loophole, as every core member function preserves the
|
|
invariants of the iterator.
|
|
|
|
``operator[]``
|
|
================
|
|
|
|
The indexing operator for a generalized iterator presents special
|
|
challenges. A random access iterator's ``operator[]`` is only
|
|
required to return something convertible to its ``value_type``.
|
|
Requiring that it return an lvalue would rule out currently-legal
|
|
random-access iterators which hold the referenced value in a data
|
|
member (e.g. `counting_iterator`_), because ``*(p+n)`` is a reference
|
|
into the temporary iterator ``p+n``, which is destroyed when
|
|
``operator[]`` returns.
|
|
|
|
Writable iterators built with ``iterator_facade`` implement the
|
|
semantics required by the preferred resolution to `issue 299`_ and
|
|
adopted by proposal `n1477`_: the result of ``p[n]`` is a proxy object
|
|
containing a copy of ``p+n``, and ``p[n] = x`` is equivalent to ``*(p
|
|
+ n) = x``. This approach will work properly for any random-access
|
|
iterator regardless of the other details of its implementation. A
|
|
user who knows more about the implementation of her iterator is free
|
|
to implement an ``operator[]`` which returns an lvalue in the derived
|
|
iterator class; it will hide the one supplied by ``iterator_facade``
|
|
from clients of her iterator.
|
|
|
|
.. _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 overrides
|
|
some of the core operations by implementing the (non-virtual) 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 that are not overriden by the
|
|
users derived class.
|
|
|
|
|
|
.. In addition, the derived
|
|
class will typically need to define some constructors.
|
|
|
|
.. Jeremy, that last sentence is also true of iterator_facade.
|
|
Perhaps we ought to cover the issue of constructors separately.
|
|
|
|
.. Talk about why we use use_default. -JGS
|
|
|
|
|
|
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 ``<iterator_helper>`` synopsis [lib.iterator.helper.synopsis]
|
|
=======================================================================
|
|
|
|
.. How's that for a name for the header? -JGS
|
|
.. Also, below I changed "not_specified" to the user-centric "use_default" -JGS
|
|
|
|
.. Isn't use_default an implementation detail ? -thw
|
|
|
|
.. Not if we want to allow the user to write stuff like
|
|
iterator_facade<Iter, use_default, some_category>. -JGS
|
|
|
|
::
|
|
|
|
struct use_default;
|
|
|
|
struct iterator_core_access { /* implementation detail */ };
|
|
|
|
template <
|
|
class Derived
|
|
, class Value
|
|
, class Category
|
|
, class Reference = Value&
|
|
, class Pointer = 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 Pointer = 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 Pointer = use_default
|
|
, class Difference = use_default
|
|
>
|
|
class indirect_iterator;
|
|
|
|
template <class Iterator>
|
|
class reverse_iterator;
|
|
|
|
template <class AdaptableUnaryFunction, class Iterator>
|
|
class transform_iterator;
|
|
|
|
template <class Predicate, class Iterator>
|
|
class filter_iterator;
|
|
|
|
template <
|
|
class Incrementable,
|
|
class Category = use_default,
|
|
class Difference = use_default
|
|
>
|
|
class counting_iterator
|
|
|
|
template <class UnaryFunction>
|
|
class function_output_iterator;
|
|
|
|
|
|
|
|
Iterator facade [lib.iterator.facade]
|
|
=====================================
|
|
|
|
``iterator_facade`` is a base class template which implements the
|
|
interface of standard iterators in terms of a few core functions
|
|
and associated types, to be supplied by a derived iterator class.
|
|
|
|
Class template ``iterator_facade``
|
|
----------------------------------
|
|
|
|
::
|
|
|
|
template <
|
|
class Derived
|
|
, class Value
|
|
, class Category
|
|
, class Reference = Value&
|
|
, class Pointer = Value*
|
|
, class Difference = ptrdiff_t
|
|
>
|
|
class iterator_facade {
|
|
public:
|
|
typedef remove_cv<Value>::type value_type;
|
|
typedef Reference reference;
|
|
typedef Pointer pointer;
|
|
typedef Difference difference_type;
|
|
typedef Category iterator_category;
|
|
|
|
reference operator*() const;
|
|
/* see below */ operator->() const;
|
|
/* unspecified */ operator[](difference_type n) const;
|
|
Derived& operator++();
|
|
Derived operator++(int);
|
|
Derived& operator--();
|
|
Derived operator--(int);
|
|
Derived& operator+=(difference_type n);
|
|
Derived& operator-=(difference_type n);
|
|
Derived operator-(difference_type n) const;
|
|
};
|
|
|
|
// Comparison operators
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition
|
|
operator ==(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator !=(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator <(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator <=(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator >(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator >=(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator >=(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
// Iterator difference
|
|
template <class Dr1, class V1, class C1, class R1, class P1, class D1,
|
|
class Dr2, class V2, class C2, class R2, class P2, class D2>
|
|
typename enable_if_interoperable<Dr1, Dr2, bool>::type
|
|
operator -(iterator_facade<Dr1, V1, C1, R1, P1, D1> const& lhs,
|
|
iterator_facade<Dr2, V2, C2, R2, P2, D2> const& rhs);
|
|
|
|
// Iterator addition
|
|
template <class Derived, class V, class C, class R, class P, class D>
|
|
Derived operator+ (iterator_facade<Derived, V, C, R, P, D> const&,
|
|
typename Derived::difference_type n)
|
|
|
|
|
|
|
|
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 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<Derived const*>(this)->dereference()``
|
|
|
|
*see below* ``operator->() const;``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
:Postconditions:
|
|
|
|
:Returns: If ``X::reference`` is a reference type, returns an object
|
|
of type ``X::pointer`` equal to::
|
|
|
|
&static_cast<Derived const*>(this)->dereference()
|
|
|
|
Otherwise returns an object of unspecified type such that, given an
|
|
object ``a`` of type ``X``, ``a->m`` is equivalent to ``(w = *a,
|
|
*w*.m)`` for some temporary object ``w`` of type ``X::value_type``.
|
|
|
|
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
|
|
*unspecified* ``operator[](difference_type n) const;``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
:Postconditions:
|
|
|
|
: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``.
|
|
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
|
|
``Derived& operator++();``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(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.
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived operator++(int);``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
++*this;
|
|
return tmp;
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived& operator--();``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->decrement();
|
|
return *this;
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived operator--(int);``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
--*this;
|
|
return tmp;
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived& operator+=(difference_type n);``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->advance(n);
|
|
return *this;
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived& operator-=(difference_type n);``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
::
|
|
|
|
static_cast<Derived*>(this)->advance(-n);
|
|
return *this;
|
|
|
|
:Postconditions:
|
|
:Returns:
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
``Derived operator-(difference_type n) const;``
|
|
|
|
:Requires:
|
|
:Effects:
|
|
|
|
Derived tmp(static_cast<Derived const*>(this));
|
|
return tmp -= n;
|
|
|
|
:Postconditions:
|
|
:Returns: ``static_cast<Derived const*>(this)->advance(-n);``
|
|
:Throws:
|
|
:Complexity:
|
|
|
|
|
|
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 implements some of
|
|
the (non-virtual) core interface functions to adapt the behaviour of
|
|
the ``Base`` type. The ``Base`` type need not meet the full
|
|
requirements of an iterator; it need only support the default
|
|
operations that are not implemented by the users derived class.
|
|
|
|
|
|
Class template ``iterator_adaptor``
|
|
-----------------------------------
|
|
|
|
::
|
|
|
|
template <
|
|
class Derived
|
|
, class Base
|
|
, class Value = use_default
|
|
, class Category = use_default
|
|
, class Reference = use_default
|
|
, class Pointer = use_default
|
|
, class Difference = use_default
|
|
>
|
|
class iterator_adaptor
|
|
: public iterator_facade<Derived, /* see details ...*/>
|
|
{
|
|
friend class iterator_core_access;
|
|
public:
|
|
iterator_adaptor();
|
|
explicit iterator_adaptor(Base iter);
|
|
Base base() const;
|
|
protected:
|
|
// Default implementation of core interface for iterator_facade
|
|
typename super_t::reference dereference() const
|
|
{ return *m_iterator; }
|
|
|
|
template <
|
|
class OtherDerived, class OtherBase, class V, class C, class R, class P, class D
|
|
>
|
|
bool equal(iterator_adaptor<OtherDerived, OtherBase, V, C, R, P, D> const& x) const
|
|
{
|
|
return m_iterator == x.base();
|
|
}
|
|
void advance(typename super_t::difference_type n)
|
|
{
|
|
m_iterator += n;
|
|
}
|
|
|
|
void increment() { ++m_iterator; }
|
|
void decrement() { --m_iterator; }
|
|
|
|
template <
|
|
class OtherDerived, class OtherBase, class V, class C, class R, class P, class D
|
|
>
|
|
typename super_t::difference_type distance_to(
|
|
iterator_adaptor<OtherDerived, OtherBase, V, C, R, P, D> const& y) const
|
|
{
|
|
return y.base() - m_iterator;
|
|
}
|
|
Base const& base_reference() const
|
|
{ return m_iterator; }
|
|
|
|
private: // exposition
|
|
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
|
|
used in the protected member functions of ``iterator_adaptor`` that
|
|
are not overriden by the ``Derived`` class. The rest of the template
|
|
parameters specify the types for the member typedefs in
|
|
``iterator_facade``. The following pseudo-code specifies the traits
|
|
types for ``iterator_adaptor``.
|
|
|
|
::
|
|
|
|
if (Value == use_default)
|
|
value_type = iterator_traits<Base>::value_type;
|
|
else
|
|
value_type = remove_cv<Value>::type;
|
|
|
|
if (Reference == use_default) {
|
|
if (Value == use_default)
|
|
reference = iterator_traits<Base>::reference;
|
|
else
|
|
reference = Value&;
|
|
} else
|
|
reference = Reference;
|
|
|
|
if (Pointer == use_default) {
|
|
if (Value == use_default)
|
|
pointer = iterator_traits<Base>::pointer;
|
|
else
|
|
pointer = Value*;
|
|
} else
|
|
pointer = Pointer;
|
|
|
|
if (Category == use_default)
|
|
iterator_category = iterator_traits<Base>::iterator_category;
|
|
else
|
|
iterator_category = Category;
|
|
|
|
if (Distance == use_default)
|
|
difference_type = iterator_traits<Base>::difference_type;
|
|
else
|
|
difference_type = Distance;
|
|
|
|
|
|
|
|
``iterator_adaptor`` operations
|
|
-------------------------------
|
|
|
|
``iterator_adaptor();``
|
|
|
|
:Requires: The ``Base`` type must be Default Constructible.
|
|
:Returns: An instance of ``iterator_adaptor`` with a
|
|
default constructed base iterator.
|
|
|
|
|
|
``explicit iterator_adaptor(Base iter);``
|
|
|
|
:Returns: An instance of ``iterator_adaptor`` with
|
|
the position specified by ``iter``.
|
|
|
|
``Base base() const;``
|
|
|
|
:Returns: A copy of base iterator object used to construct
|
|
``*this``, but at the same position as ``*this``.
|
|
|
|
|
|
|
|
Specialized adaptors [lib.iterator.special.adaptors]
|
|
====================================================
|
|
|
|
.. The requirements for all of these need to be written *much* more
|
|
formally -DWA
|
|
|
|
|
|
|
|
Indirect iterator
|
|
-----------------
|
|
|
|
The indirect iterator adapts an iterator by applying an *extra*
|
|
dereference inside of ``operator*()``. For example, this iterator
|
|
adaptor makes it possible to view a container of pointers
|
|
(e.g. ``list<foo*>``) as if it were a container of the pointed-to type
|
|
(e.g. ``list<foo>``) .
|
|
|
|
|
|
Class template ``indirect_iterator``
|
|
....................................
|
|
|
|
::
|
|
|
|
template <
|
|
class Iterator
|
|
, class Value = use_default
|
|
, class Category = use_default
|
|
, class Reference = use_default
|
|
, class Pointer = use_default
|
|
, class Difference = use_default
|
|
>
|
|
class indirect_iterator
|
|
: public iterator_adaptor</* see discussion */>
|
|
{
|
|
typedef iterator_adaptor</* see discussion */> super_t;
|
|
friend class iterator_core_access;
|
|
public:
|
|
indirect_iterator();
|
|
indirect_iterator(Iterator x);
|
|
template <
|
|
class Iterator2, class Value2, class Category2
|
|
, class Reference2, class Pointer2, class Difference2
|
|
>
|
|
indirect_iterator(
|
|
indirect_iterator<
|
|
Iterator2, Value2, Category2, Reference2, Pointer2, Difference2
|
|
> const& y
|
|
, typename enable_if_convertible<Iterator2, Iterator>::type* = 0
|
|
);
|
|
private: // as-if specification
|
|
typename super_t::reference dereference() const
|
|
{
|
|
return **this->base();
|
|
}
|
|
};
|
|
|
|
|
|
``indirect_iterator`` requirements
|
|
..................................
|
|
|
|
The ``value_type`` of the ``Iterator`` template parameter should
|
|
itself be dereferenceable. The return type of the ``operator*`` for
|
|
the ``value_type`` must be the same type as the ``Reference`` template
|
|
parameter. The ``Value`` template parameter will be the ``value_type``
|
|
for the ``indirect_iterator``, unless ``Value`` is const. If ``Value``
|
|
is ``const X``, then ``value_type`` will be *non-* ``const X``. The
|
|
default for ``Value`` is
|
|
|
|
::
|
|
|
|
iterator_traits< iterator_traits<Iterator>::value_type >::value_type
|
|
|
|
If the default is used for ``Value``, then there must be a valid
|
|
specialization of ``iterator_traits`` for the value type of the base
|
|
iterator.
|
|
|
|
The ``Reference`` parameter will be the ``reference`` type of the
|
|
``indirect_iterator``. The default is ``Value&``.
|
|
|
|
The ``Pointer`` parameter will be the ``pointer`` type of the
|
|
``indirect_iterator``. The default is ``Value*``.
|
|
|
|
The ``Category`` parameter is the ``iterator_category`` type for the
|
|
``indirect_iterator``. The default is
|
|
``iterator_traits<Iterator>::iterator_category``.
|
|
|
|
The indirect iterator will model the most refined standard traversal
|
|
concept that is modelled by the ``Iterator`` type. The indirect
|
|
iterator will model the most refined standard access concept that is
|
|
modelled 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 Pointer2, class Difference2
|
|
>
|
|
indirect_iterator(
|
|
indirect_iterator<
|
|
Iterator2, Value2, Category2, Reference2, Pointer2, Difference2
|
|
> const& y
|
|
, typename enable_if_convertible<Iterator2, Iterator>::type* = 0
|
|
);
|
|
|
|
:Requires: ``this->base()`` and ``y.base()`` must be mutually convertible.
|
|
: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 Iterator>
|
|
class reverse_iterator :
|
|
public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
|
|
{
|
|
typedef iterator_adaptor< reverse_iterator<Iterator>, Iterator > super_t;
|
|
friend class iterator_core_access;
|
|
public:
|
|
reverse_iterator() {}
|
|
|
|
explicit reverse_iterator(Iterator x)
|
|
: super_t(x) {}
|
|
|
|
template<class OtherIterator>
|
|
reverse_iterator(
|
|
reverse_iterator<OtherIterator> const& r
|
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
|
)
|
|
: super_t(r.base())
|
|
{}
|
|
|
|
private: // as-if specification
|
|
typename super_t::reference dereference() const { return *prior(this->base()); }
|
|
|
|
void increment() { super_t::decrement(); }
|
|
void decrement() { super_t::increment(); }
|
|
|
|
void advance(typename super_t::difference_type n)
|
|
{
|
|
super_t::advance(-n);
|
|
}
|
|
|
|
template <class OtherIterator>
|
|
typename super_t::difference_type
|
|
distance_to(reverse_iterator<OtherIterator> const& y) const
|
|
{
|
|
return -super_t::distance_to(y);
|
|
}
|
|
};
|
|
|
|
|
|
``reverse_iterator`` requirements
|
|
.................................
|
|
|
|
The base ``Iterator`` must be a model of Bidirectional Traversal
|
|
Iterator. The resulting ``reverse_iterator`` will be a model of the
|
|
most refined standard traversal and access concepts that are modeled
|
|
by ``Iterator``.
|
|
|
|
|
|
``reverse_iterator();``
|
|
|
|
:Requires: ``Iterator`` must be Default Constructible.
|
|
:Returns: An instance of ``reverse_iterator`` with a
|
|
default constructed base object.
|
|
|
|
``explicit reverse_iterator(Iterator x);``
|
|
|
|
:Returns: An instance of ``reverse_iterator`` with a
|
|
base object copy constructed from ``x``.
|
|
|
|
|
|
::
|
|
|
|
template<class OtherIterator>
|
|
reverse_iterator(
|
|
reverse_iterator<OtherIterator> const& r
|
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
|
);
|
|
|
|
:Requires: ``this->base()`` and ``r.base()`` must be mutually convertible.
|
|
:Returns: An instance of ``reverse_iterator`` that is a copy of ``r``.
|
|
|
|
|
|
Transform iterator
|
|
------------------
|
|
|
|
The transform iterator adapts an iterator by applying some function
|
|
object to the result of dereferencing the iterator. In other words,
|
|
the ``operator*`` of the transform iterator first dereferences the
|
|
base iterator, passes the result of this to the function object, and
|
|
then returns the result.
|
|
|
|
|
|
Class template ``transform_iterator``
|
|
.....................................
|
|
|
|
::
|
|
|
|
template <class AdaptableUnaryFunction, class Iterator>
|
|
class transform_iterator
|
|
: public iterator_adaptor</* see discussion */>
|
|
{
|
|
typedef iterator_adaptor</* see discussion */> super_t;
|
|
friend class iterator_core_access;
|
|
public:
|
|
transform_iterator() { }
|
|
|
|
transform_iterator(Iterator const& x, AdaptableUnaryFunction f)
|
|
: super_t(x), m_f(f) { }
|
|
|
|
template<class OtherIterator>
|
|
transform_iterator(
|
|
transform_iterator<AdaptableUnaryFunction, OtherIterator> const& t
|
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
|
)
|
|
: super_t(t.base()), m_f(t.functor()) {}
|
|
|
|
AdaptableUnaryFunction functor() const
|
|
{ return m_f; }
|
|
|
|
private: // as-if specification
|
|
typename super_t::value_type dereference() const
|
|
{ return m_f(super_t::dereference()); }
|
|
|
|
AdaptableUnaryFunction m_f;
|
|
};
|
|
|
|
|
|
``transform_iterator`` requirements
|
|
...................................
|
|
|
|
Write me. Use ``result_of``?
|
|
|
|
|
|
Filter iterator
|
|
---------------
|
|
|
|
The filter iterator adaptor creates a view of an iterator range in
|
|
which some elements of the range are skipped over. A predicate
|
|
function object controls which elements are skipped. When the
|
|
predicate is applied to an element, if it returns ``true`` then the
|
|
element is retained and if it returns ``false`` then the element is
|
|
skipped over. When skipping over elements, it is necessary for the
|
|
filter adaptor to know when to stop so as to avoid going past the end
|
|
of the underlying range. Therefore the constructor of the filter
|
|
iterator takes two iterator parameters: the position for the filtered
|
|
iterator and the end of the range.
|
|
|
|
|
|
|
|
Class template ``filter_iterator``
|
|
..................................
|
|
|
|
::
|
|
|
|
template <class Predicate, class Iterator>
|
|
class filter_iterator
|
|
: public iterator_adaptor<
|
|
filter_iterator<Predicate, Iterator>, Iterator
|
|
, use_default
|
|
, /* see details */
|
|
>
|
|
{
|
|
public:
|
|
filter_iterator();
|
|
filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
|
|
filter_iterator(Iterator x, Iterator end = Iterator());
|
|
template<class OtherIterator>
|
|
filter_iterator(
|
|
filter_iterator<Predicate, OtherIterator> const& t
|
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
|
|
);
|
|
Predicate predicate() const;
|
|
Iterator end() const;
|
|
|
|
private: // as-if specification
|
|
void increment()
|
|
{
|
|
++(this->base_reference());
|
|
satisfy_predicate();
|
|
}
|
|
|
|
void satisfy_predicate()
|
|
{
|
|
while (this->base() != this->m_end && !this->m_predicate(*this->base()))
|
|
++(this->base_reference());
|
|
}
|
|
|
|
Predicate m_predicate;
|
|
Iterator m_end;
|
|
};
|
|
|
|
|
|
``filter_iterator`` requirements
|
|
--------------------------------
|
|
|
|
The base ``Iterator`` parameter must be a model of Readable Iterator
|
|
and Single Pass Iterator. The resulting ``filter_iterator`` will be a
|
|
model of Forward Traversal Iterator if ``Iterator`` is, otherwise the
|
|
``filter_iterator`` will be a model of Single Pass Iterator. The
|
|
access category of the ``filter_iterator`` will be the most refined
|
|
standard access category that is modeled by ``Iterator``.
|
|
|
|
.. 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<Iterator>::value_type``, and where the type of
|
|
``p(x)`` must be convertible to ``bool``.
|
|
|
|
|
|
|
|
``filter_iterator`` operations
|
|
------------------------------
|
|
|
|
``filter_iterator();``
|
|
|
|
:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible.
|
|
:Returns: a ``filter_iterator`` whose
|
|
predicate is a default constructed ``Predicate`` and
|
|
whose ``end`` is a default constructed ``Iterator``.
|
|
|
|
|
|
``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());``
|
|
|
|
:Returns: A ``filter_iterator`` at position ``x`` that filters according
|
|
to predicate ``f`` and that will not increment past ``end``.
|
|
|
|
|
|
``filter_iterator(Iterator x, Iterator end = Iterator());``
|
|
|
|
:Requires: ``Predicate`` must be Default Constructible.
|
|
:Returns: A ``filter_iterator`` at position ``x`` that filters
|
|
according to a default constructed ``Predicate``
|
|
and that will not increment past ``end``.
|
|
|
|
|
|
::
|
|
|
|
template <class OtherIterator>
|
|
filter_iterator(
|
|
filter_iterator<Predicate, OtherIterator> const& t
|
|
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
|
|
);``
|
|
|
|
:Requires: ``*this`` and ``t`` must be mutually convertible.
|
|
: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 the
|
|
current value of the base object. The other operations are implemented
|
|
by the base object, as per the inheritance from ``iterator_adaptor``.
|
|
|
|
|
|
Class template ``counting_iterator``
|
|
....................................
|
|
|
|
::
|
|
|
|
template <class Incrementable, class Category = not_specified, class Difference = not_specified>
|
|
class counting_iterator
|
|
: public iterator_adaptor<
|
|
counting_iterator<Incrementable, Category, Difference>
|
|
, Incrementable
|
|
, Incrementable
|
|
, /* see details for category */
|
|
, Incrementable const&
|
|
, Incrementable const*
|
|
, /* see details for difference */>
|
|
{
|
|
typedef iterator_adaptor</* see details */> super_t;
|
|
friend class iterator_core_access;
|
|
public:
|
|
counting_iterator();
|
|
counting_iterator(counting_iterator const& rhs);
|
|
counting_iterator(Incrementable x);
|
|
private:
|
|
|
|
typename super_t::reference dereference() const
|
|
{
|
|
return this->base_reference();
|
|
}
|
|
|
|
// Why is this complicated? Why not let the default impl handle this? -JGS
|
|
template <class OtherIncrementable>
|
|
difference_type
|
|
distance_to(counting_iterator<OtherIncrementable> const& y) const
|
|
{
|
|
typedef typename mpl::if_<
|
|
detail::is_numeric<Incrementable>
|
|
, detail::number_distance<difference_type, Incrementable, OtherIncrementable>
|
|
, detail::iterator_distance<difference_type, Incrementable, OtherIncrementable>
|
|
>::type d;
|
|
|
|
return d::distance(this->base(), y.base());
|
|
}
|
|
};
|
|
|
|
``counting_iterator`` requirements
|
|
----------------------------------
|
|
|
|
The ``Incrementable`` type must be Default Constructible, Copy
|
|
Constructible, and Assignable. Also, the ``Incrementable`` type must
|
|
provide access to an associated ``difference_type`` and
|
|
``iterator_category`` through the ``counting_iterator_traits`` class.
|
|
|
|
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_traits<Incrementable>::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``.
|
|
|
|
.. Why isn't this constructor templated and use
|
|
enable_if_interoperable like the rest? That version
|
|
was ifdef'd out in the impl. Why? -JGS
|
|
|
|
|
|
``counting_iterator(Incrementable x);``
|
|
|
|
:Returns: An instance of ``counting_iterator`` with its base
|
|
object copy constructed from ``x``.
|
|
|
|
|
|
Function output iterator
|
|
------------------------
|
|
|
|
The function output iterator adaptor makes it easier to create custom
|
|
output iterators. The adaptor takes a unary function and creates a
|
|
model of Output Iterator. Each item assigned to the output iterator is
|
|
passed as an argument to the unary function. The motivation for this
|
|
iterator is that creating a conforming output iterator is non-trivial,
|
|
particularly because the proper implementation usually requires a
|
|
proxy object.
|
|
|
|
|
|
Class template ``function_output_iterator``
|
|
...........................................
|
|
|
|
::
|
|
|
|
template <class UnaryFunction>
|
|
class function_output_iterator {
|
|
public:
|
|
typedef iterator_tag<
|
|
writable_iterator_tag
|
|
, incrementable_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 <class T> output_proxy& operator=(const T& value);
|
|
};
|
|
output_proxy operator*();
|
|
function_output_iterator& operator++();
|
|
function_output_iterator& operator++(int);
|
|
};
|
|
|
|
|
|
``function_output_iterator`` requirements
|
|
-----------------------------------------
|
|
|
|
The ``UnaryFunction`` must be Assignable, Copy Constructible, and the
|
|
expression ``f(x)`` must be valid, where ``f`` is an object of type
|
|
``UnaryFunction`` and ``x`` is an object of a type accepted by ``f``.
|
|
The resulting ``function_output_iterator`` is a model of the Writable
|
|
and Incrementable Iterator concepts.
|
|
|
|
|
|
``function_output_iterator`` operations
|
|
---------------------------------------
|
|
|
|
``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());``
|
|
|
|
:Returns: An instance of ``function_output_iterator`` with
|
|
``f`` stored as a data member.
|
|
|
|
|
|
``output_proxy operator*();``
|
|
|
|
:Returns: An instance of ``output_proxy`` constructed with
|
|
a copy of the unary function ``f``.
|
|
|
|
|
|
``function_output_iterator& operator++();``
|
|
|
|
:Returns: ``*this``
|
|
|
|
|
|
``function_output_iterator& operator++(int);``
|
|
|
|
:Returns: ``*this``
|
|
|
|
|
|
``function_output_iterator::output_proxy`` operations
|
|
-----------------------------------------------------
|
|
|
|
``output_proxy(UnaryFunction& f);``
|
|
|
|
:Returns: An instance of ``output_proxy`` with ``f`` stored as
|
|
a data member.
|
|
|
|
|
|
``template <class T> output_proxy& operator=(const T& value);``
|
|
|
|
:Effects:
|
|
::
|
|
|
|
m_f(value);
|
|
return *this;
|
|
|
|
|
|
|
|
.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template
|
|
Patterns, C++ Report, February 1995, pp. 24-27.
|