123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 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``.
|