facade-and-adaptor.rst 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. .. Distributed under the Boost
  2. .. Software License, Version 1.0. (See accompanying
  3. .. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. +++++++++++++++++++++++++++++
  5. Iterator Facade and Adaptor
  6. +++++++++++++++++++++++++++++
  7. :Author: David Abrahams, Jeremy Siek, Thomas Witt
  8. :Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
  9. :organization: `Boost Consulting`_, Indiana University `Open Systems
  10. Lab`_, `Zephyr Associates, Inc.`_
  11. :date: $Date$
  12. :Number: This is a revised version of N1530_\ =03-0113, which was
  13. accepted for Technical Report 1 by the C++ standard
  14. committee's library working group.
  15. .. Version 1.9 of this ReStructuredText document corresponds to
  16. n1530_, the paper accepted by the LWG.
  17. .. _n1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html
  18. :copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
  19. .. _`Boost Consulting`: http://www.boost-consulting.com
  20. .. _`Open Systems Lab`: http://www.osl.iu.edu
  21. .. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com
  22. :abstract: We propose a set of class templates that help programmers
  23. build standard-conforming iterators, both from scratch and
  24. by adapting other iterators.
  25. .. contents:: Table of Contents
  26. ============
  27. Motivation
  28. ============
  29. Iterators play an important role in modern C++ programming. The
  30. iterator is the central abstraction of the algorithms of the Standard
  31. Library, allowing algorithms to be re-used in in a wide variety of
  32. contexts. The C++ Standard Library contains a wide variety of useful
  33. iterators. Every one of the standard containers comes with constant
  34. and mutable iterators [#mutable]_, and also reverse versions of those
  35. same iterators which traverse the container in the opposite direction.
  36. The Standard also supplies ``istream_iterator`` and
  37. ``ostream_iterator`` for reading from and writing to streams,
  38. ``insert_iterator``, ``front_insert_iterator`` and
  39. ``back_insert_iterator`` for inserting elements into containers, and
  40. ``raw_storage_iterator`` for initializing raw memory [7].
  41. Despite the many iterators supplied by the Standard Library, obvious
  42. and useful iterators are missing, and creating new iterator types is
  43. still a common task for C++ programmers. The literature documents
  44. several of these, for example line_iterator [3] and Constant_iterator
  45. [9]. The iterator abstraction is so powerful that we expect
  46. programmers will always need to invent new iterator types.
  47. Although it is easy to create iterators that *almost* conform to the
  48. standard, the iterator requirements contain subtleties which can make
  49. creating an iterator which *actually* conforms quite difficult.
  50. Further, the iterator interface is rich, containing many operators
  51. that are technically redundant and tedious to implement. To automate
  52. the repetitive work of constructing iterators, we propose
  53. ``iterator_facade``, an iterator base class template which provides
  54. the rich interface of standard iterators and delegates its
  55. implementation to member functions of the derived class. In addition
  56. to reducing the amount of code necessary to create an iterator, the
  57. ``iterator_facade`` also provides compile-time error detection.
  58. Iterator implementation mistakes that often go unnoticed are turned
  59. into compile-time errors because the derived class implementation must
  60. match the expectations of the ``iterator_facade``.
  61. A common pattern of iterator construction is the adaptation of one
  62. iterator to form a new one. The functionality of an iterator is
  63. composed of four orthogonal aspects: traversal, indirection, equality
  64. comparison and distance measurement. Adapting an old iterator to
  65. create a new one often saves work because one can reuse one aspect of
  66. functionality while redefining the other. For example, the Standard
  67. provides ``reverse_iterator``, which adapts any Bidirectional Iterator
  68. by inverting its direction of traversal. As with plain iterators,
  69. iterator adaptors defined outside the Standard have become commonplace
  70. in the literature:
  71. * Checked iter[13] adds bounds-checking to an existing iterator.
  72. * The iterators of the View Template Library[14], which adapts
  73. containers, are themselves adaptors over the underlying iterators.
  74. * Smart iterators [5] adapt an iterator's dereferencing behavior by
  75. applying a function object to the object being referenced and
  76. returning the result.
  77. * Custom iterators [4], in which a variety of adaptor types are enumerated.
  78. * Compound iterators [1], which access a slice out of a container of containers.
  79. * Several iterator adaptors from the MTL [12]. The MTL contains a
  80. strided iterator, where each call to ``operator++()`` moves the
  81. iterator ahead by some constant factor, and a scaled iterator, which
  82. multiplies the dereferenced value by some constant.
  83. .. [#concept] We use the term concept to mean a set of requirements
  84. that a type must satisfy to be used with a particular template
  85. parameter.
  86. .. [#mutable] The term mutable iterator refers to iterators over objects that
  87. can be changed by assigning to the dereferenced iterator, while
  88. constant iterator refers to iterators over objects that cannot be
  89. modified.
  90. To fulfill the need for constructing adaptors, we propose the
  91. ``iterator_adaptor`` class template. Instantiations of
  92. ``iterator_adaptor`` serve as a base classes for new iterators,
  93. providing the default behavior of forwarding all operations to the
  94. underlying iterator. The user can selectively replace these features
  95. in the derived iterator class. This proposal also includes a number
  96. of more specialized adaptors, such as the ``transform_iterator`` that
  97. applies some user-specified function during the dereference of the
  98. iterator.
  99. ========================
  100. Impact on the Standard
  101. ========================
  102. This proposal is purely an addition to the C++ standard library.
  103. However, note that this proposal relies on the proposal for New
  104. Iterator Concepts.
  105. ========
  106. Design
  107. ========
  108. Iterator Concepts
  109. =================
  110. This proposal is formulated in terms of the new ``iterator concepts``
  111. as proposed in n1550_, since user-defined and especially adapted
  112. iterators suffer from the well known categorization problems that are
  113. inherent to the current iterator categories.
  114. .. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm
  115. This proposal does not strictly depend on proposal n1550_, as there
  116. is a direct mapping between new and old categories. This proposal
  117. could be reformulated using this mapping if n1550_ was not accepted.
  118. Interoperability
  119. ================
  120. The question of iterator interoperability is poorly addressed in the
  121. current standard. There are currently two defect reports that are
  122. concerned with interoperability issues.
  123. Issue 179_ concerns the fact that mutable container iterator types
  124. are only required to be convertible to the corresponding constant
  125. iterator types, but objects of these types are not required to
  126. interoperate in comparison or subtraction expressions. This situation
  127. is tedious in practice and out of line with the way built in types
  128. work. This proposal implements the proposed resolution to issue
  129. 179_, as most standard library implementations do nowadays. In other
  130. words, if an iterator type A has an implicit or user defined
  131. conversion to an iterator type B, the iterator types are interoperable
  132. and the usual set of operators are available.
  133. Issue 280_ concerns the current lack of interoperability between
  134. reverse iterator types. The proposed new reverse_iterator template
  135. fixes the issues raised in 280. It provides the desired
  136. interoperability without introducing unwanted overloads.
  137. .. _179: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#179
  138. .. _280: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#280
  139. Iterator Facade
  140. ===============
  141. .. include:: iterator_facade_body.rst
  142. Iterator Adaptor
  143. ================
  144. .. include:: iterator_adaptor_body.rst
  145. Specialized Adaptors
  146. ====================
  147. This proposal also contains several examples of specialized adaptors
  148. which were easily implemented using ``iterator_adaptor``:
  149. * ``indirect_iterator``, which iterates over iterators, pointers,
  150. or smart pointers and applies an extra level of dereferencing.
  151. * A new ``reverse_iterator``, which inverts the direction of a Base
  152. iterator's motion, while allowing adapted constant and mutable
  153. iterators to interact in the expected ways (unlike those in most
  154. implementations of C++98).
  155. * ``transform_iterator``, which applies a user-defined function object
  156. to the underlying values when dereferenced.
  157. * ``filter_iterator``, which provides a view of an iterator range in
  158. which some elements of the underlying range are skipped.
  159. .. _counting:
  160. * ``counting_iterator``, which adapts any incrementable type
  161. (e.g. integers, iterators) so that incrementing/decrementing the
  162. adapted iterator and dereferencing it produces successive values of
  163. the Base type.
  164. * ``function_output_iterator``, which makes it easier to create custom
  165. output iterators.
  166. Based on examples in the Boost library, users have generated many new
  167. adaptors, among them a permutation adaptor which applies some
  168. permutation to a random access iterator, and a strided adaptor, which
  169. adapts a random access iterator by multiplying its unit of motion by a
  170. constant factor. In addition, the Boost Graph Library (BGL) uses
  171. iterator adaptors to adapt other graph libraries, such as LEDA [10]
  172. and Stanford GraphBase [8], to the BGL interface (which requires C++
  173. Standard compliant iterators).
  174. ===============
  175. Proposed Text
  176. ===============
  177. Header ``<iterator_helper>`` synopsis [lib.iterator.helper.synopsis]
  178. =======================================================================
  179. ::
  180. struct use_default;
  181. struct iterator_core_access { /* implementation detail */ };
  182. template <
  183. class Derived
  184. , class Value
  185. , class CategoryOrTraversal
  186. , class Reference = Value&
  187. , class Difference = ptrdiff_t
  188. >
  189. class iterator_facade;
  190. template <
  191. class Derived
  192. , class Base
  193. , class Value = use_default
  194. , class CategoryOrTraversal = use_default
  195. , class Reference = use_default
  196. , class Difference = use_default
  197. >
  198. class iterator_adaptor;
  199. template <
  200. class Iterator
  201. , class Value = use_default
  202. , class CategoryOrTraversal = use_default
  203. , class Reference = use_default
  204. , class Difference = use_default
  205. >
  206. class indirect_iterator;
  207. template <class Dereferenceable>
  208. struct pointee;
  209. template <class Dereferenceable>
  210. struct indirect_reference;
  211. template <class Iterator>
  212. class reverse_iterator;
  213. template <
  214. class UnaryFunction
  215. , class Iterator
  216. , class Reference = use_default
  217. , class Value = use_default
  218. >
  219. class transform_iterator;
  220. template <class Predicate, class Iterator>
  221. class filter_iterator;
  222. template <
  223. class Incrementable
  224. , class CategoryOrTraversal = use_default
  225. , class Difference = use_default
  226. >
  227. class counting_iterator;
  228. template <class UnaryFunction>
  229. class function_output_iterator;
  230. Iterator facade [lib.iterator.facade]
  231. =====================================
  232. .. include:: iterator_facade_abstract.rst
  233. Class template ``iterator_facade``
  234. ----------------------------------
  235. .. include:: iterator_facade_ref.rst
  236. Iterator adaptor [lib.iterator.adaptor]
  237. =======================================
  238. .. include:: iterator_adaptor_abstract.rst
  239. Class template ``iterator_adaptor``
  240. -----------------------------------
  241. .. include:: iterator_adaptor_ref.rst
  242. Specialized adaptors [lib.iterator.special.adaptors]
  243. ====================================================
  244. The ``enable_if_convertible<X,Y>::type`` expression used in
  245. this section is for exposition purposes. The converting constructors
  246. for specialized adaptors should be only be in an overload set provided
  247. that an object of type ``X`` is implicitly convertible to an object of
  248. type ``Y``.
  249. The signatures involving ``enable_if_convertible`` should behave
  250. *as-if* ``enable_if_convertible`` were defined to be::
  251. template <bool> enable_if_convertible_impl
  252. {};
  253. template <> enable_if_convertible_impl<true>
  254. { struct type; };
  255. template<typename From, typename To>
  256. struct enable_if_convertible
  257. : enable_if_convertible_impl<is_convertible<From,To>::value>
  258. {};
  259. If an expression other than the default argument is used to supply
  260. the value of a function parameter whose type is written in terms
  261. of ``enable_if_convertible``, the program is ill-formed, no
  262. diagnostic required.
  263. [*Note:* The ``enable_if_convertible`` approach uses SFINAE to
  264. take the constructor out of the overload set when the types are not
  265. implicitly convertible.
  266. ]
  267. Indirect iterator
  268. -----------------
  269. .. include:: indirect_iterator_abstract.rst
  270. Class template ``pointee``
  271. ....................................
  272. .. include:: pointee_ref.rst
  273. Class template ``indirect_reference``
  274. .....................................
  275. .. include:: indirect_reference_ref.rst
  276. Class template ``indirect_iterator``
  277. ....................................
  278. .. include:: indirect_iterator_ref.rst
  279. Reverse iterator
  280. ----------------
  281. .. include:: reverse_iterator_abstract.rst
  282. Class template ``reverse_iterator``
  283. ...................................
  284. .. include:: reverse_iterator_ref.rst
  285. Transform iterator
  286. ------------------
  287. .. include:: transform_iterator_abstract.rst
  288. Class template ``transform_iterator``
  289. .....................................
  290. .. include:: transform_iterator_ref.rst
  291. Filter iterator
  292. ---------------
  293. .. include:: filter_iterator_abstract.rst
  294. Class template ``filter_iterator``
  295. ..................................
  296. .. include:: filter_iterator_ref.rst
  297. Counting iterator
  298. -----------------
  299. .. include:: counting_iterator_abstract.rst
  300. Class template ``counting_iterator``
  301. ....................................
  302. .. include:: counting_iterator_ref.rst
  303. Function output iterator
  304. ------------------------
  305. .. include:: func_output_iter_abstract.rst
  306. Class template ``function_output_iterator``
  307. ...........................................
  308. .. include:: func_output_iter_ref.rst
  309. .. LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate
  310. LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv
  311. LocalWords: GraphBase struct ptrdiff UnaryFunction const int typename bool pp
  312. LocalWords: lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo
  313. LocalWords: dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd
  314. LocalWords: OtherIncrementable Coplien