removed iterator_tag and reworded some paragraphs

[SVN r21046]
This commit is contained in:
Jeremy Siek
2003-12-01 16:38:36 +00:00
parent 8cfa950f10
commit 52e34b2e26

View File

@ -299,74 +299,21 @@ given in the following diagram.
Like the old iterator requirements, we provide tags for purposes of Like the old iterator requirements, we provide tags for purposes of
dispatching based on the traversal concepts. The tags are related via dispatching based on the traversal concepts. The tags are related via
inheritance so that a tag is convertible to another tag if the concept inheritance so that a tag is convertible to another tag if the concept
associated with the first tag is a refinement of the second tag. associated with the first tag is a refinement of the second tag. Our
Since the access concepts are not related via refinement, but instead design reuses ``iterator_traits<Iter>::iterator_category`` as the
cover orthogonal issues, we do not use tags for the access concepts, access mechanism for the traversal tag. If an iterator wishes to meet
but instead use the equivalent of a bit field. the requirements of both a new iterator concept and an old iterator
concept, it can use an iterator category type that inherits from both
the the old iterator tag and the new traversal tag.
We provide an access mechanism for mapping iterator types to the new We do not provide tags for the purposes of dispatching based on the
traversal tags and access bit field. Our design reuses access concepts. There are two reasons: we could not find a way to
``iterator_traits<Iter>::iterator_category`` as the access automatically infer the right access tags for old-style iterators and
mechanism. To that end, the access and traversal information is the need for dispatching based on the access concepts is not as great.
bundled into a single type using the following `iterator_tag` class.
:: A difficult design decision concerned the ``operator[]``. The direct
approach for specifying ``operator[]`` would have a return type of
enum iterator_access { readable_iterator = 1, writable_iterator = 2, ``reference``; the same as ``operator*``. However, going in this
swappable_iterator = 4, lvalue_iterator = 8 };
template <unsigned int access_bits, class TraversalTag>
struct iterator_tag : /* appropriate old category or categories */ {
static const iterator_access access =
(iterator_access)access_bits &
(readable_iterator | writable_iterator | swappable_iterator);
typedef TraversalTag traversal;
};
The ``access_bits`` argument is declared to be ``unsigned int``
instead of the enum ``iterator_access`` for convenience of use. For
example, the expression ``(readable_iterator | writable_iterator)``
produces an unsigned int, not an ``iterator_access``. The purpose of
the ``lvalue_iterator`` part of the ``iterator_access`` enum is to
communicate to ``iterator_tag`` whether the reference type is an
lvalue so that the appropriate old category can be chosen for the base
class. The ``lvalue_iterator`` bit is not recorded in the
``iterator_tag::access`` data member.
The ``iterator_tag`` class template is derived from the appropriate
iterator tag or tags from the old requirements based on the access
bits and traversal tag passed as template parameters. The algorithm
for determining the old tag or 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, 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 several helper classes that make it convenient to
obtain the access and traversal characteristics of an iterator. These
helper classes work both for iterators whose ``iterator_category`` is
``iterator_tag`` and also for iterators using the original iterator
categories.
::
template <class Iterator> struct is_readable { typedef ... type; };
template <class Iterator> struct is_writable { typedef ... type; };
template <class Iterator> struct is_swappable { typedef ... type; };
template <class Iterator> struct traversal_category { typedef ... type; };
We do not include a helper class ``is_lvalue_iterator`` because that
can easily be deduced by checking whether
``iterator_traits<Iterator>::reference`` is a real reference.
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 direction would mean that an iterator satisfying the old Random Access
Iterator requirements would not necessarily be a model of Readable or Iterator requirements would not necessarily be a model of Readable or
Writable Lvalue Iterator. Instead we have chosen a design that Writable Lvalue Iterator. Instead we have chosen a design that