issues.rst 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Problem with ``is_writable`` and ``is_swappable`` in N1550_
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4. .. _N1550: http://www.boost-consulting.com/writing/n1550.html
  5. .. _N1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html
  6. :Author: David Abrahams and Jeremy Siek
  7. :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu
  8. :Organization: `Boost Consulting`_, Indiana University Bloomington
  9. :date: $Date$
  10. :Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and
  11. distribution is subject to the Boost Software License,
  12. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
  13. at http://www.boost.org/LICENSE_1_0.txt)
  14. .. _`Boost Consulting`: http://www.boost-consulting.com
  15. .. contents:: Table of Contents
  16. ==============
  17. Introduction
  18. ==============
  19. The ``is_writable`` and ``is_swappable`` traits classes in N1550_
  20. provide a mechanism for determining at compile time if an iterator
  21. type is a model of the new Writable Iterator and Swappable Iterator
  22. concepts, analogous to ``iterator_traits<X>::iterator_category``
  23. for the old iterator concepts. For backward compatibility,
  24. ``is_writable`` and ``is_swappable`` not only work with new
  25. iterators, but they also are intended to work for old
  26. iterators (iterators that meet the requirements for one of the
  27. iterator concepts in the current standard). In the case of old
  28. iterators, the writability and swapability is deduced based on the
  29. ``iterator_category`` and also the ``reference`` type. The
  30. specification for this deduction gives false positives for forward
  31. iterators that have non-assignable value types.
  32. To review, the part of the ``is_writable`` trait definition which
  33. applies to old iterators is::
  34. if (cat is convertible to output_iterator_tag)
  35. return true;
  36. else if (cat is convertible to forward_iterator_tag
  37. and iterator_traits<Iterator>::reference is a
  38. mutable reference)
  39. return true;
  40. else
  41. return false;
  42. Suppose the ``value_type`` of the iterator ``It`` has a private
  43. assignment operator::
  44. class B {
  45. public:
  46. ...
  47. private:
  48. B& operator=(const B&);
  49. };
  50. and suppose the ``reference`` type of the iterator is ``B&``. In
  51. that case, ``is_writable<It>::value`` will be true when in fact
  52. attempting to write into ``B`` will cause an error.
  53. The same problem applies to ``is_swappable``.
  54. ====================
  55. Proposed Resolution
  56. ====================
  57. 1. Remove the ``is_writable`` and ``is_swappable`` traits, and remove the
  58. requirements in the Writable Iterator and Swappable Iterator concepts
  59. that require their models to support these traits.
  60. 2. Change the ``is_readable`` specification to be:
  61. ``is_readable<X>::type`` is ``true_type`` if the
  62. result type of ``X::operator*`` is convertible to
  63. ``iterator_traits<X>::value_type`` and is ``false_type``
  64. otherwise. Also, ``is_readable`` is required to satisfy
  65. the requirements for the UnaryTypeTrait concept
  66. (defined in the type traits proposal).
  67. Remove the requirement for support of the ``is_readable`` trait from
  68. the Readable Iterator concept.
  69. 3. Remove the ``iterator_tag`` class.
  70. 4. Change the specification of ``traversal_category`` to::
  71. traversal-category(Iterator) =
  72. let cat = iterator_traits<Iterator>::iterator_category
  73. if (cat is convertible to incrementable_iterator_tag)
  74. return cat; // Iterator is a new iterator
  75. else if (cat is convertible to random_access_iterator_tag)
  76. return random_access_traversal_tag;
  77. else if (cat is convertible to bidirectional_iterator_tag)
  78. return bidirectional_traversal_tag;
  79. else if (cat is convertible to forward_iterator_tag)
  80. return forward_traversal_tag;
  81. else if (cat is convertible to input_iterator_tag)
  82. return single_pass_iterator_tag;
  83. else if (cat is convertible to output_iterator_tag)
  84. return incrementable_iterator_tag;
  85. else
  86. return null_category_tag;
  87. ==========
  88. Rationale
  89. ==========
  90. 1. There are two reasons for removing ``is_writable``
  91. and ``is_swappable``. The first is that we do not know of
  92. a way to fix the specification so that it gives the correct
  93. answer for all iterators. Second, there was only a weak
  94. motivation for having ``is_writable`` and ``is_swappable``
  95. there in the first place. The main motivation was simply
  96. uniformity: we have tags for the old iterator categories
  97. so we should have tags for the new iterator categories.
  98. While having tags and the capability to dispatch based
  99. on the traversal categories is often used, we see
  100. less of a need for dispatching based on writability
  101. and swappability, since typically algorithms
  102. that need these capabilities have no alternative if
  103. they are not provided.
  104. 2. We discovered that the ``is_readable`` trait can be implemented
  105. using only the iterator type itself and its ``value_type``.
  106. Therefore we remove the requirement for ``is_readable`` from the
  107. Readable Iterator concept, and change the definition of
  108. ``is_readable`` so that it works for any iterator type.
  109. 3. The purpose of the ``iterator_tag`` class was to
  110. bundle the traversal and access category tags
  111. into the ``iterator_category`` typedef.
  112. With ``is_writable`` and ``is_swappable`` gone, and
  113. ``is_readable`` no longer in need of special hints,
  114. there is no reason for iterators to provide
  115. information about the access capabilities of an iterator.
  116. Thus there is no need for the ``iterator_tag``. The
  117. traversal tag can be directly used for the
  118. ``iterator_category``. If a new iterator is intended to be backward
  119. compatible with old iterator concepts, a tag type
  120. that is convertible to both one of the new traversal tags
  121. and also to an old iterator tag can be created and use
  122. for the ``iterator_category``.
  123. 4. The changes to the specification of ``traversal_category`` are a
  124. direct result of the removal of ``iterator_tag``.