forked from boostorg/iterator
edits and commentary
[SVN r1184]
This commit is contained in:
@@ -30,10 +30,13 @@
|
|||||||
|
|
||||||
The standard iterator categories and requirements are flawed because
|
The standard iterator categories and requirements are flawed because
|
||||||
they use a single hierarchy of concepts to address two orthogonal
|
they use a single hierarchy of concepts to address two orthogonal
|
||||||
issues: *iterator traversal* and *value access*. As a result
|
issues: *iterator traversal* and *value access*. As a result, many
|
||||||
algorithms with type requirements expressed by the iterator
|
algorithms with requirements expressed in terms of the iterator
|
||||||
requirements are too strict. Also many concrete iterators can not be
|
categories are too strict. Also, many real-world iterators can not be
|
||||||
accurately categorized. The current iterator concept hierarchy is
|
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
|
geared towards iterator traversal (hence the category names), while
|
||||||
requirements that address value access sneak in at various places. The
|
requirements that address value access sneak in at various places. The
|
||||||
following table gives a summary of the current value access
|
following table gives a summary of the current value access
|
||||||
@@ -70,8 +73,8 @@ disk-based collections.
|
|||||||
|
|
||||||
.. _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 difficult 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_). There 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
|
||||||
@@ -81,6 +84,11 @@ iterator) or 2) return the ``value_type`` or a proxy from
|
|||||||
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
|
||||||
|
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
|
||||||
|
|
||||||
.. _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
|
||||||
|
|
||||||
@@ -123,13 +131,17 @@ things happen:
|
|||||||
Impact on the Standard
|
Impact on the Standard
|
||||||
========================
|
========================
|
||||||
|
|
||||||
The new iterator concepts are backwards compatible with the old
|
The new iterator concepts are backward-compatible with the old
|
||||||
iterator requirements, and old iterators are forward compatible with
|
iterator requirements, and old iterators are forward-compatible with
|
||||||
the new iterator concepts. That is to say, iterators that satisfy the
|
the new iterator concepts. That is to say, iterators that satisfy the
|
||||||
old requirements also satisfy appropriate concepts in the new system,
|
old requirements also satisfy appropriate concepts in the new system,
|
||||||
and iterators modeling the new concepts will automatically satisfy the
|
and iterators modeling the new concepts will automatically satisfy the
|
||||||
appropriate old requirements.
|
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
|
||||||
|
|
||||||
The algorithms in the standard library benefit from the new iterator
|
The algorithms in the standard library benefit from the new iterator
|
||||||
concepts because the new concepts provide a more accurate way to
|
concepts because the new concepts provide a more accurate way to
|
||||||
express their type requirements. The result is algorithms that are
|
express their type requirements. The result is algorithms that are
|
||||||
@@ -230,7 +242,7 @@ combined into a single type using the following `iterator_tag` class.
|
|||||||
::
|
::
|
||||||
|
|
||||||
template <class AccessTag, class TraversalTag>
|
template <class AccessTag, class TraversalTag>
|
||||||
struct iterator_tag : /* appropriate old category */
|
struct iterator_tag : /* appropriate old category or categories */
|
||||||
{
|
{
|
||||||
typedef AccessTag access;
|
typedef AccessTag access;
|
||||||
typedef TraversalTag traversal;
|
typedef TraversalTag traversal;
|
||||||
@@ -530,7 +542,7 @@ Addition to [lib.iterator.synopsis]
|
|||||||
template <class Iterator> struct traversal_category;
|
template <class Iterator> struct traversal_category;
|
||||||
|
|
||||||
template <class AccessTag, class TraversalTag>
|
template <class AccessTag, class TraversalTag>
|
||||||
struct iterator_tag : /* appropriate old category */ {
|
struct iterator_tag : /* appropriate old category or categories */ {
|
||||||
typedef AccessTag access;
|
typedef AccessTag access;
|
||||||
typedef TraversalTag traversal;
|
typedef TraversalTag traversal;
|
||||||
};
|
};
|
||||||
@@ -556,7 +568,6 @@ Addition to [lib.iterator.synopsis]
|
|||||||
struct null_category_tag { };
|
struct null_category_tag { };
|
||||||
struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};
|
struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {};
|
||||||
|
|
||||||
|
|
||||||
Addition to [lib.iterator.traits]
|
Addition to [lib.iterator.traits]
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
@@ -569,28 +580,38 @@ pseudo-code.
|
|||||||
::
|
::
|
||||||
|
|
||||||
inherit-category(access-tag, traversal-tag) =
|
inherit-category(access-tag, traversal-tag) =
|
||||||
if (access-tag is convertible to readable_lvalue_iterator_tag
|
(access-tag is convertible to readable_lvalue_iterator_tag
|
||||||
or access-tag is convertible to writable_lvalue_iterator_tag) {
|
or access-tag is convertible to writable_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)
|
(traversal-tag is convertible to random_access_traversal_tag)
|
||||||
return bidirectional_iterator_tag;
|
? random_access_iterator_tag
|
||||||
else if (traversal-tag is convertible to forward_traversal_tag)
|
|
||||||
return forward_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;
|
|
||||||
|
|
||||||
|
: (traversal-tag is convertible to bidirectional_traversal_tag)
|
||||||
|
? bidirectional_iterator_tag
|
||||||
|
|
||||||
|
: (traversal-tag is convertible to forward_traversal_tag)
|
||||||
|
? forward_iterator_tag
|
||||||
|
|
||||||
|
: null_category_tag
|
||||||
|
)
|
||||||
|
: (access-tag is convertible to readable_writable_iterator_tag
|
||||||
|
and traversal-tag is convertible to single_pass_iterator_tag)
|
||||||
|
? input_output_iterator_tag
|
||||||
|
|
||||||
|
: (access-tag is convertible to readable_iterator_tag
|
||||||
|
and traversal-tag is convertible to single_pass_iterator_tag)
|
||||||
|
? input_iterator_tag
|
||||||
|
|
||||||
|
: (access-tag is convertible to writable_iterator_tag
|
||||||
|
and traversal-tag is convertible to incrementable_iterator_tag)
|
||||||
|
? output_iterator_tag
|
||||||
|
|
||||||
|
: null_category_tag;
|
||||||
|
|
||||||
|
.. Jeremy, I'm not attached to the rewrite above; I just did it to see
|
||||||
|
if I could make it clearer please feel free to rewrite if you don't
|
||||||
|
like it.
|
||||||
|
|
||||||
The ``access_category`` and ``traversal_category`` class templates are
|
The ``access_category`` and ``traversal_category`` class templates are
|
||||||
traits classes. For iterators whose
|
traits classes. For iterators whose
|
||||||
|
Reference in New Issue
Block a user