3fd1c34411
[SVN r86673]
153 lines
5.9 KiB
ReStructuredText
153 lines
5.9 KiB
ReStructuredText
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Problem with ``is_writable`` and ``is_swappable`` in N1550_
|
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
.. _N1550: http://www.boost-consulting.com/writing/n1550.html
|
|
.. _N1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html
|
|
|
|
:Author: David Abrahams and Jeremy Siek
|
|
:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu
|
|
:Organization: `Boost Consulting`_, Indiana University Bloomington
|
|
:date: $Date$
|
|
:Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and
|
|
distribution is subject to the Boost Software License,
|
|
Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
|
|
at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
.. _`Boost Consulting`: http://www.boost-consulting.com
|
|
|
|
.. contents:: Table of Contents
|
|
|
|
==============
|
|
Introduction
|
|
==============
|
|
|
|
The ``is_writable`` and ``is_swappable`` traits classes in N1550_
|
|
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::
|
|
|
|
if (cat is convertible to output_iterator_tag)
|
|
return true;
|
|
else if (cat is convertible to forward_iterator_tag
|
|
and iterator_traits<Iterator>::reference is a
|
|
mutable reference)
|
|
return true;
|
|
else
|
|
return false;
|
|
|
|
Suppose the ``value_type`` of the iterator ``It`` has a private
|
|
assignment operator::
|
|
|
|
class B {
|
|
public:
|
|
...
|
|
private:
|
|
B& operator=(const B&);
|
|
};
|
|
|
|
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``.
|
|
|
|
|
|
====================
|
|
Proposed Resolution
|
|
====================
|
|
|
|
1. Remove the ``is_writable`` and ``is_swappable`` traits, and remove the
|
|
requirements in the Writable Iterator and Swappable Iterator concepts
|
|
that require their models to support these traits.
|
|
|
|
2. Change the ``is_readable`` specification to be:
|
|
``is_readable<X>::type`` is ``true_type`` if the
|
|
result type of ``X::operator*`` is convertible to
|
|
``iterator_traits<X>::value_type`` and is ``false_type``
|
|
otherwise. Also, ``is_readable`` is required to satisfy
|
|
the requirements for the UnaryTypeTrait concept
|
|
(defined in the type traits proposal).
|
|
|
|
Remove the requirement for support of the ``is_readable`` trait from
|
|
the Readable Iterator concept.
|
|
|
|
|
|
3. Remove the ``iterator_tag`` class.
|
|
|
|
4. Change the specification of ``traversal_category`` to::
|
|
|
|
traversal-category(Iterator) =
|
|
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;
|
|
|
|
|
|
==========
|
|
Rationale
|
|
==========
|
|
|
|
1. There are two reasons for removing ``is_writable``
|
|
and ``is_swappable``. The first is that we do not know of
|
|
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
|
|
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
|
|
on the traversal categories is often used, we see
|
|
less of a need for dispatching based on writability
|
|
and swappability, since typically algorithms
|
|
that need these capabilities have no alternative if
|
|
they are not provided.
|
|
|
|
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. The purpose of the ``iterator_tag`` class was to
|
|
bundle the traversal and access category tags
|
|
into the ``iterator_category`` typedef.
|
|
With ``is_writable`` and ``is_swappable`` gone, and
|
|
``is_readable`` no longer in need of special hints,
|
|
there is no reason for iterators to provide
|
|
information about the access capabilities of an iterator.
|
|
Thus there is no need for the ``iterator_tag``. The
|
|
traversal tag can be directly used for the
|
|
``iterator_category``. If a new iterator is intended to be backward
|
|
compatible with old iterator concepts, a tag type
|
|
that is convertible to both one of the new traversal tags
|
|
and also to an old iterator tag can be created and use
|
|
for the ``iterator_category``.
|
|
|
|
4. The changes to the specification of ``traversal_category`` are a
|
|
direct result of the removal of ``iterator_tag``.
|
|
|