mirror of
https://github.com/boostorg/iterator.git
synced 2025-07-29 12:27:33 +02:00
Edits for clarity and correctness.
[SVN r20831]
This commit is contained in:
124
doc/issues.rst
124
doc/issues.rst
@ -23,17 +23,18 @@
|
||||
==============
|
||||
|
||||
The ``is_writable`` and ``is_swappable`` traits classes in N1550_
|
||||
provide a mechanism for determining at compile time if a type is a
|
||||
model of the new Writable Iterator and Swappable Iterator concepts,
|
||||
analogous to ``iterator_traits<X>::iterator_category`` for the old
|
||||
iterator concepts. For backward compatibility, ``is_writable`` and
|
||||
``is_swappable`` not only work with new iterators, but they also are
|
||||
intended to work for old iterators (iterators that meet the
|
||||
requirements for one of the iterator concepts in the current
|
||||
standard). In the case of old iterators, the writability and
|
||||
swapability is deduced based on the ``iterator_category`` and also the
|
||||
``reference`` type. The specification for this deduction gives false
|
||||
positives for forward iterators that have non-assignable value types.
|
||||
provide a mechanism for determining at compile time if an iterator
|
||||
type is a model of the new Writable Iterator and Swappable Iterator
|
||||
concepts, analogous to ``iterator_traits<X>::iterator_category``
|
||||
for the old iterator concepts. For backward compatibility,
|
||||
``is_writable`` and ``is_swappable`` not only work with new
|
||||
iterators, but they also are intended to work for old
|
||||
iterators (iterators that meet the requirements for one of the
|
||||
iterator concepts in the current standard). In the case of old
|
||||
iterators, the writability and swapability is deduced based on the
|
||||
``iterator_category`` and also the ``reference`` type. The
|
||||
specification for this deduction gives false positives for forward
|
||||
iterators that have non-assignable value types.
|
||||
|
||||
To review, the part of the ``is_writable`` trait definition which
|
||||
applies to old iterators is::
|
||||
@ -47,8 +48,8 @@ applies to old iterators is::
|
||||
else
|
||||
return false;
|
||||
|
||||
Suppose the ``value_type`` of the iterator has a private assignment
|
||||
operator::
|
||||
Suppose the ``value_type`` of the iterator ``It`` has a private
|
||||
assignment operator::
|
||||
|
||||
class B {
|
||||
public:
|
||||
@ -57,9 +58,9 @@ operator::
|
||||
B& operator=(const B&);
|
||||
};
|
||||
|
||||
and suppose the ``reference`` type of the iterator is ``B&``. Then
|
||||
``is_writable`` will deduce true when in fact attempting to write into
|
||||
``B`` will cause an error.
|
||||
and suppose the ``reference`` type of the iterator is ``B&``. In
|
||||
that case, ``is_writable<It>::value`` will be true when in fact
|
||||
attempting to write into ``B`` will cause an error.
|
||||
|
||||
The same problem applies to ``is_swappable``.
|
||||
|
||||
@ -81,64 +82,78 @@ The same problem applies to ``is_swappable``.
|
||||
Remove the requirement for support of the ``is_readable`` trait from
|
||||
the Readable Iterator concept.
|
||||
|
||||
.. We should give some attention to the UnaryTypeTrait concept,
|
||||
which requires the trait to be derived from either true_type or
|
||||
false_type (as of the last LWG meeting).
|
||||
|
||||
3. Change ``iterator_tag`` to::
|
||||
|
||||
template <class Value, class Reference, class Traversal>
|
||||
struct iterator_tag;
|
||||
|
||||
The argument for ``Value`` must be the value type of the
|
||||
iterator, ``Reference`` must be the return type of
|
||||
``operator*`` [*]_, and ``Traversal`` the traversal tag for the
|
||||
iterator.
|
||||
The argument for ``Value`` must be the ``value_type`` of the
|
||||
iterator, possibly const-qualified, ``Reference`` must be the
|
||||
return type of ``operator*`` [*]_, and ``Traversal`` the
|
||||
traversal tag for the iterator.
|
||||
|
||||
``iterator_tag`` is required to be convertible to both the
|
||||
``Traversal`` tag and also to the appropriate old iterator category
|
||||
tag, as specified by the following pseudo-code::
|
||||
.. I think the language above is still too informal. There is no
|
||||
"the iterator", when considering iterator_tag in isolation.
|
||||
Perhaps that language belongs in a non-normative note
|
||||
|
||||
inherit-category(Value, Reference, Traversal) =
|
||||
``iterator_tag<Value,Reference,Traversal>`` is required to be
|
||||
convertible to both ``Traversal`` tag and also to the
|
||||
``iterator_category`` type specified by the following
|
||||
pseudo-code::
|
||||
|
||||
old-category(Value, Reference, Traversal) =
|
||||
if (Reference is a reference
|
||||
and Traversal is convertible to forward_traversal_tag) {
|
||||
and Traversal is convertible to forward_traversal_tag)
|
||||
{
|
||||
if (Traversal is convertible to random_access_traversal_tag)
|
||||
return random_access_iterator_tag;
|
||||
else if (Traversal is convertible to bidirectional_traversal_tag)
|
||||
return bidirectional_iterator_tag;
|
||||
else
|
||||
return forward_iterator_tag;
|
||||
} else if (Traversal is convertible to single_pass_traversal_tag
|
||||
and Reference is convertible to Value) {
|
||||
}
|
||||
else if (Traversal is convertible to single_pass_traversal_tag
|
||||
and Reference is convertible to Value)
|
||||
{
|
||||
if (Value is const)
|
||||
return input_iterator_tag;
|
||||
else
|
||||
return input_output_iterator_tag;
|
||||
} else
|
||||
return output_iterator_tag;
|
||||
|
||||
|
||||
|
||||
.. I reformatted the code for legibility; sorry.
|
||||
|
||||
.. [*] Instead of saying "return type of operator*", we could have
|
||||
said ``iterator_traits<X>::reference``. However, the standard
|
||||
specifies nothing about ``iterator_traits<X>::reference``,
|
||||
which we believe is a defect. Once the defect is fixed,
|
||||
the above could be rephrased.
|
||||
specifies nothing about ``iterator_traits<X>::reference`` in
|
||||
many cases, which we believe is a defect. Furthermore, in some
|
||||
cases it explicitly differs from the return type of
|
||||
``operator*``, for example see ``istreambuf_iterator``.
|
||||
|
||||
|
||||
4. Change the specification of ``traversal_category`` to::
|
||||
|
||||
traversal-category(Iterator) =
|
||||
let cat = iterator_traits<Iterator>::iterator_category
|
||||
if (cat convertible to incrementable_iterator_tag)
|
||||
return cat; // Iterator is a new iterator
|
||||
else if (cat is convertible to random_access_iterator_tag)
|
||||
return random_access_traversal_tag;
|
||||
else if (cat is convertible to bidirectional_iterator_tag)
|
||||
return bidirectional_traversal_tag;
|
||||
else if (cat is convertible to forward_iterator_tag)
|
||||
return forward_traversal_tag;
|
||||
else if (cat is convertible to input_iterator_tag)
|
||||
return single_pass_iterator_tag;
|
||||
else if (cat is convertible to output_iterator_tag)
|
||||
return incrementable_iterator_tag;
|
||||
else
|
||||
return null_category_tag;
|
||||
let cat = iterator_traits<Iterator>::iterator_category
|
||||
if (cat is convertible to incrementable_iterator_tag)
|
||||
return cat; // Iterator is a new iterator
|
||||
else if (cat is convertible to random_access_iterator_tag)
|
||||
return random_access_traversal_tag;
|
||||
else if (cat is convertible to bidirectional_iterator_tag)
|
||||
return bidirectional_traversal_tag;
|
||||
else if (cat is convertible to forward_iterator_tag)
|
||||
return forward_traversal_tag;
|
||||
else if (cat is convertible to input_iterator_tag)
|
||||
return single_pass_iterator_tag;
|
||||
else if (cat is convertible to output_iterator_tag)
|
||||
return incrementable_iterator_tag;
|
||||
else
|
||||
return null_category_tag;
|
||||
|
||||
|
||||
==========
|
||||
@ -150,7 +165,7 @@ The same problem applies to ``is_swappable``.
|
||||
a way to fix the specification so that it gives the correct
|
||||
answer for all iterators. Second, there was only a weak
|
||||
motivation for having ``is_writable`` and ``is_swappable``
|
||||
there in the first place. The main motivation was simply
|
||||
there in the first place. The main motivation was simply
|
||||
uniformity: we have tags for the old iterator categories
|
||||
so we should have tags for the new iterator categories.
|
||||
While having tags and the capability to dispatch based
|
||||
@ -160,12 +175,11 @@ The same problem applies to ``is_swappable``.
|
||||
that need these capabilities have no alternative if
|
||||
they are not provided.
|
||||
|
||||
2. We discovered that the ``is_readable`` trait can be
|
||||
implemented without special hints from the iterator.
|
||||
Therefore we remove the requirement for ``is_readable``
|
||||
from the Readable Iterator concept, and change
|
||||
the definition of ``is_readable`` so that it works
|
||||
for any iterator type.
|
||||
2. We discovered that the ``is_readable`` trait can be implemented
|
||||
using only the iterator type itself and its ``value_type``.
|
||||
Therefore we remove the requirement for ``is_readable`` from the
|
||||
Readable Iterator concept, and change the definition of
|
||||
``is_readable`` so that it works for any iterator type.
|
||||
|
||||
3. With ``is_writable`` and ``is_swappable`` gone, and
|
||||
``is_readable`` no longer in need of special hints,
|
||||
@ -181,7 +195,7 @@ The same problem applies to ``is_swappable``.
|
||||
deduce the appropriate old iterator category. The
|
||||
``Value`` and ``Reference`` parameters fill this need.
|
||||
Note that this solution cleans up the issue that John
|
||||
Maddock raised on the reflector about the non-uniformity
|
||||
Maddock raised on the reflector (``c++std-lib-12187``) about the non-uniformity
|
||||
of the lvalue bit.
|
||||
|
||||
4. The changes to the specification of ``traversal_category`` are a
|
||||
|
Reference in New Issue
Block a user