forked from boostorg/iterator
more edits
[SVN r1213]
This commit is contained in:
@@ -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
|
safety loophole, as every core member function preserves the
|
||||||
invariants of the iterator.
|
invariants of the iterator.
|
||||||
|
|
||||||
operator[]()
|
``operator[]``
|
||||||
============
|
================
|
||||||
|
|
||||||
For operator[]() ``iterator_facade`` implements the semantics required
|
The indexing operator for a generalized iterator presents special challenges;
|
||||||
in the proposed resolution to issue `299`_ and adopted by proposal `n1477`_.
|
|
||||||
I.e. operator[]() is not required to return an lvalue.
|
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
|
.. _`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
|
For ``readable iterators`` the reference type is only required to be
|
||||||
convertible to the value type, but accessing members through
|
convertible to the value type, but accessing members through
|
||||||
|
@@ -71,39 +71,49 @@ nonintuitive that at least one implementation erroneously assigns
|
|||||||
not return true references: there is the often cited example of
|
not return true references: there is the often cited example of
|
||||||
disk-based collections.
|
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
|
.. _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
|
.. Another example of a hard-to-categorize iterator is a counting
|
||||||
iterator: an iterator the returns a sequence of integers when
|
iterator: an iterator the returns a sequence of integers when
|
||||||
incremented and dereferenced (see counting_iterator_). There are two
|
incremented and dereferenced (see counting_iterator_). This iterator are two
|
||||||
ways to implement this iterator, 1) return a true reference from
|
ways to implement this iterator, 1) return a true reference from
|
||||||
``operator[]`` (a reference to an integer data member of the counting
|
``operator[]`` (a reference to an integer data member of the counting
|
||||||
iterator) or 2) return the ``value_type`` or a proxy from
|
iterator) or 2) return the ``value_type`` or a proxy from
|
||||||
``operator[]``. Option 1) runs into the problems discussed in `issue
|
``operator[]``. Option 1) runs into the problems discussed in `issue
|
||||||
198`_, the reference will not be valid after the iterator is
|
198`_: the reference will not be valid after the iterator is
|
||||||
destroyed. Option 2) is therefore a better choice, but then we have a
|
destroyed. Option 2) is therefore a better choice, but then we have a
|
||||||
counting iterator that cannot be a random access iterator.
|
counting iterator that cannot be a random access iterator.
|
||||||
|
|
||||||
.. Jeremy, option 1 is NOT an option, since there's no way to return a
|
.. 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
|
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
|
what you're saying here. I'd fix it myself, but I'm not sure what
|
||||||
you're getting at. -DWA
|
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
|
.. _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
|
.. _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
|
Another difficult-to-categorize iterator is the transform iterator, an
|
||||||
applies a unary function object to the dereference value of the
|
adaptor which applies a unary function object to the dereferenced
|
||||||
wrapped iterator (see `transform_iterator`_). For unary functions
|
value of the some underlying iterator (see `transform_iterator`_).
|
||||||
such as ``times`` the return type of ``operator*`` clearly needs
|
For unary functions such as ``times``, the return type of
|
||||||
to be the ``result_type`` of the function object, which is typically
|
``operator*`` clearly needs to be the ``result_type`` of the function
|
||||||
not a reference. However, with the current iterator requirements, if
|
object, which is typically not a reference. Because random access
|
||||||
you wrap ``int*`` with a transform iterator, you do not get a random
|
iterators are prequired to return lvalues from ``operator*``, if you
|
||||||
access iterator as expected, but an input iterator.
|
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
|
.. _`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
|
`Boost Graph Library`_. These iterators return vertex and edge
|
||||||
descriptors, which are lightweight handles created on-the-fly. They
|
descriptors, which are lightweight handles created on-the-fly. They
|
||||||
must be returned by-value. As a result, their current standard
|
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
|
current standard iterator categories. As a result, the following bad
|
||||||
things happen:
|
things happen:
|
||||||
|
|
||||||
- Iterators are often miss-categorized.
|
- Iterators are often mis-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
|
- Algorithm requirements are more strict than necessary, because they
|
||||||
return type.
|
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
|
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 matches
|
Writable Lvalue Iterator. Instead we have chosen a design that
|
||||||
the resolution of `issue 299`_. So ``operator[]`` is only required to
|
matches the resolution of `issue 299`_: ``operator[]`` is only
|
||||||
return something convertible to the ``value_type`` (for a Readable
|
required to return something convertible to the ``value_type`` (for a
|
||||||
Iterator), and is required to support assignment ``i[n] = t`` (for a
|
Readable Iterator), and is required to support assignment ``i[n] = t``
|
||||||
Writable Iterator).
|
(for a Writable Iterator).
|
||||||
|
|
||||||
|
|
||||||
===============
|
===============
|
||||||
|
Reference in New Issue
Block a user