more edits

[SVN r1213]
This commit is contained in:
Dave Abrahams
2003-04-27 00:20:50 +00:00
parent 73030b3ac8
commit af92b555d3
2 changed files with 54 additions and 35 deletions

View File

@@ -266,17 +266,25 @@ It is important to note that ``iterator_core_access`` does not open a
safety loophole, as every core member function preserves the
invariants of the iterator.
operator[]()
============
``operator[]``
================
For operator[]() ``iterator_facade`` implements the semantics required
in the proposed resolution to issue `299`_ and adopted by proposal `n1477`_.
I.e. operator[]() is not required to return an lvalue.
The indexing operator for a generalized iterator presents special challenges;
Writable iterators built with ``iterator_facade`` implement the
semantics required by the proposed resolution to issue `299`_ and
adopted by proposal `n1477`_: ``p[n] = x`` is equivalent to ``*(p + n)
= x``. To make that possible regardless of the other details of the
iterator's implementation, the return type of ``operator[]`` is a
proxy object containing a copy of
result of indexing the iterator is assignable
iterator
.. _`299`: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#299
operator->()
============
``operator->``
==============
For ``readable iterators`` the reference type is only required to be
convertible to the value type, but accessing members through

View File

@@ -71,39 +71,49 @@ nonintuitive that at least one implementation erroneously assigns
not return true references: there is the often cited example of
disk-based collections.
.. I wonder if the disk-based collection argument is valid? I would
tend to do that with an internally stored lvalue. -DWA
.. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96
Another example of a hard-to-categorize iterator is a counting
iterator: an iterator the returns a sequence of integers when
incremented and dereferenced (see counting_iterator_). There are two
ways to implement this iterator, 1) return a true reference from
``operator[]`` (a reference to an integer data member of the counting
iterator) or 2) return the ``value_type`` or a proxy from
``operator[]``. 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.
.. Another example of a hard-to-categorize iterator is a counting
iterator: an iterator the returns a sequence of integers when
incremented and dereferenced (see counting_iterator_). This iterator are two
ways to implement this iterator, 1) return a true reference from
``operator[]`` (a reference to an integer data member of the counting
iterator) or 2) return the ``value_type`` or a proxy from
``operator[]``. 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.
.. Jeremy, option 1 is NOT an option, since there's no way to return a
live reference from operator[]. I think you need to clarify/rework
what you're saying here. I'd fix it myself, but I'm not sure what
you're getting at. -DWA
.. On second thought, I think the whole paragraph is bogus (sorry).
The conclusion for option 2, "but then we have a counting iterator
that cannot be a random access iterator" is wrong, too: returning a
value from operator[] is compatible with the random access iterator
requirements. I commented it out. -DWA
.. _counting_iterator: http://www.boost.org/libs/utility/counting_iterator.htm
.. _issue 198: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#198
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 `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. 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.
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 prequired 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 fourth example is found in the vertex and edge iterators of the
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
@@ -121,10 +131,11 @@ 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.
- 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.
========================
@@ -276,11 +287,11 @@ 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 resolution of `issue 299`_. So ``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).
Writable Lvalue Iterator. Instead we have chosen a design that
matches the 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).
===============