summaryrefslogtreecommitdiff
path: root/libs/iterator/doc/facade-and-adaptor.rst
blob: bfe5786a1584a69d5d461e55ba3e85956bed1699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
.. Distributed under 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)

+++++++++++++++++++++++++++++
 Iterator Facade and Adaptor
+++++++++++++++++++++++++++++

:Author: David Abrahams, Jeremy Siek, Thomas Witt
:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
:organization: `Boost Consulting`_, Indiana University `Open Systems
               Lab`_, `Zephyr Associates, Inc.`_
:date: $Date: 2006-09-11 18:27:29 -0400 (Mon, 11 Sep 2006) $

:Number: This is a revised version of N1530_\ =03-0113, which was
         accepted for Technical Report 1 by the C++ standard
         committee's library working group.  

.. Version 1.9 of this ReStructuredText document corresponds to
   n1530_, the paper accepted by the LWG.

.. _n1530: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1530.html

:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. 

.. _`Boost Consulting`: http://www.boost-consulting.com
.. _`Open Systems Lab`: http://www.osl.iu.edu
.. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com

:abstract: We propose a set of class templates that help programmers
           build standard-conforming iterators, both from scratch and
           by adapting other iterators.

.. contents:: Table of Contents

============
 Motivation
============

Iterators play an important role in modern C++ programming. The
iterator is the central abstraction of the algorithms of the Standard
Library, allowing algorithms to be re-used in in a wide variety of
contexts.  The C++ Standard Library contains a wide variety of useful
iterators. Every one of the standard containers comes with constant
and mutable iterators [#mutable]_, and also reverse versions of those
same iterators which traverse the container in the opposite direction.
The Standard also supplies ``istream_iterator`` and
``ostream_iterator`` for reading from and writing to streams,
``insert_iterator``, ``front_insert_iterator`` and
``back_insert_iterator`` for inserting elements into containers, and
``raw_storage_iterator`` for initializing raw memory [7].

Despite the many iterators supplied by the Standard Library, obvious
and useful iterators are missing, and creating new iterator types is
still a common task for C++ programmers.  The literature documents
several of these, for example line_iterator [3] and Constant_iterator
[9].  The iterator abstraction is so powerful that we expect
programmers will always need to invent new iterator types.

Although it is easy to create iterators that *almost* conform to the
standard, the iterator requirements contain subtleties which can make
creating an iterator which *actually* conforms quite difficult.
Further, the iterator interface is rich, containing many operators
that are technically redundant and tedious to implement.  To automate
the repetitive work of constructing iterators, we propose
``iterator_facade``, an iterator base class template which provides
the rich interface of standard iterators and delegates its
implementation to member functions of the derived class.  In addition
to reducing the amount of code necessary to create an iterator, the
``iterator_facade`` also provides compile-time error detection.
Iterator implementation mistakes that often go unnoticed are turned
into compile-time errors because the derived class implementation must
match the expectations of the ``iterator_facade``.

A common pattern of iterator construction is the adaptation of one
iterator to form a new one.  The functionality of an iterator is
composed of four orthogonal aspects: traversal, indirection, equality
comparison and distance measurement.  Adapting an old iterator to
create a new one often saves work because one can reuse one aspect of
functionality while redefining the other.  For example, the Standard
provides ``reverse_iterator``, which adapts any Bidirectional Iterator
by inverting its direction of traversal.  As with plain iterators,
iterator adaptors defined outside the Standard have become commonplace
in the literature:

* Checked iter[13] adds bounds-checking to an existing iterator.

* The iterators of the View Template Library[14], which adapts
  containers, are themselves adaptors over the underlying iterators.

* Smart iterators [5] adapt an iterator's dereferencing behavior by
  applying a function object to the object being referenced and
  returning the result.

* Custom iterators [4], in which a variety of adaptor types are enumerated.

* Compound iterators [1], which access a slice out of a container of containers.

* Several iterator adaptors from the MTL [12].  The MTL contains a
  strided iterator, where each call to ``operator++()`` moves the
  iterator ahead by some constant factor, and a scaled iterator, which
  multiplies the dereferenced value by some constant.

.. [#concept] We use the term concept to mean a set of requirements
   that a type must satisfy to be used with a particular template
   parameter.

.. [#mutable] The term mutable iterator refers to iterators over objects that
   can be changed by assigning to the dereferenced iterator, while
   constant iterator refers to iterators over objects that cannot be
   modified.

To fulfill the need for constructing adaptors, we propose the
``iterator_adaptor`` class template.  Instantiations of
``iterator_adaptor`` serve as a base classes for new iterators,
providing the default behavior of forwarding all operations to the
underlying iterator.  The user can selectively replace these features
in the derived iterator class.  This proposal also includes a number
of more specialized adaptors, such as the ``transform_iterator`` that
applies some user-specified function during the dereference of the
iterator.

========================
 Impact on the Standard
========================

This proposal is purely an addition to the C++ standard library.
However, note that this proposal relies on the proposal for New
Iterator Concepts.

========
 Design
========

Iterator Concepts
=================

This proposal is formulated in terms of the new ``iterator concepts``
as proposed in n1550_, since user-defined and especially adapted
iterators suffer from the well known categorization problems that are
inherent to the current iterator categories.

.. _n1550: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1550.html

This proposal does not strictly depend on proposal n1550_, as there
is a direct mapping between new and old categories. This proposal
could be reformulated using this mapping if n1550_ was not accepted.

Interoperability
================

The question of iterator interoperability is poorly addressed in the
current standard.  There are currently two defect reports that are
concerned with interoperability issues.

Issue 179_ concerns the fact that mutable container iterator types
are only required to be convertible to the corresponding constant
iterator types, but objects of these types are not required to
interoperate in comparison or subtraction expressions.  This situation
is tedious in practice and out of line with the way built in types
work.  This proposal implements the proposed resolution to issue
179_, as most standard library implementations do nowadays. In other
words, if an iterator type A has an implicit or user defined
conversion to an iterator type B, the iterator types are interoperable
and the usual set of operators are available.

Issue 280_ concerns the current lack of interoperability between
reverse iterator types. The proposed new reverse_iterator template
fixes the issues raised in 280. It provides the desired
interoperability without introducing unwanted overloads.

.. _179: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#179
.. _280: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#280


Iterator Facade
===============

.. include:: iterator_facade_body.rst

Iterator Adaptor
================

.. include:: iterator_adaptor_body.rst

Specialized Adaptors
====================

This proposal also contains several examples of specialized adaptors
which were easily implemented using ``iterator_adaptor``:

* ``indirect_iterator``, which iterates over iterators, pointers,
  or smart pointers and applies an extra level of dereferencing.

* A new ``reverse_iterator``, which inverts the direction of a Base
  iterator's motion, while allowing adapted constant and mutable
  iterators to interact in the expected ways (unlike those in most
  implementations of C++98).

* ``transform_iterator``, which applies a user-defined function object
  to the underlying values when dereferenced.

* ``filter_iterator``, which provides a view of an iterator range in
  which some elements of the underlying range are skipped.

.. _counting: 

* ``counting_iterator``, which adapts any incrementable type
  (e.g. integers, iterators) so that incrementing/decrementing the
  adapted iterator and dereferencing it produces successive values of
  the Base type.

* ``function_output_iterator``, which makes it easier to create custom
  output iterators.

Based on examples in the Boost library, users have generated many new
adaptors, among them a permutation adaptor which applies some
permutation to a random access iterator, and a strided adaptor, which
adapts a random access iterator by multiplying its unit of motion by a
constant factor.  In addition, the Boost Graph Library (BGL) uses
iterator adaptors to adapt other graph libraries, such as LEDA [10]
and Stanford GraphBase [8], to the BGL interface (which requires C++
Standard compliant iterators).

===============
 Proposed Text
===============


Header ``<iterator_helper>`` synopsis    [lib.iterator.helper.synopsis]
=======================================================================


::

  struct use_default;

  struct iterator_core_access { /* implementation detail */ };
  
  template <
      class Derived
    , class Value
    , class CategoryOrTraversal
    , class Reference  = Value&
    , class Difference = ptrdiff_t
  >
  class iterator_facade;

  template <
      class Derived
    , class Base
    , class Value      = use_default
    , class CategoryOrTraversal  = use_default
    , class Reference  = use_default
    , class Difference = use_default
  >
  class iterator_adaptor;
  
  template <
      class Iterator
    , class Value = use_default
    , class CategoryOrTraversal = use_default
    , class Reference = use_default
    , class Difference = use_default
  >
  class indirect_iterator;
  
  template <class Dereferenceable>
  struct pointee;

  template <class Dereferenceable>
  struct indirect_reference;

  template <class Iterator>
  class reverse_iterator;

  template <
      class UnaryFunction
    , class Iterator
    , class Reference = use_default
    , class Value = use_default
  >
  class transform_iterator;

  template <class Predicate, class Iterator>
  class filter_iterator;

  template <
      class Incrementable
    , class CategoryOrTraversal  = use_default
    , class Difference = use_default
  >
  class counting_iterator;

  template <class UnaryFunction>
  class function_output_iterator;



Iterator facade [lib.iterator.facade]
=====================================

.. include:: iterator_facade_abstract.rst

Class template ``iterator_facade``
----------------------------------

.. include:: iterator_facade_ref.rst

Iterator adaptor [lib.iterator.adaptor]
=======================================

.. include:: iterator_adaptor_abstract.rst

Class template ``iterator_adaptor``
-----------------------------------

.. include:: iterator_adaptor_ref.rst


Specialized adaptors [lib.iterator.special.adaptors]
====================================================


The ``enable_if_convertible<X,Y>::type`` expression used in
this section is for exposition purposes. The converting constructors
for specialized adaptors should be only be in an overload set provided
that an object of type ``X`` is implicitly convertible to an object of
type ``Y``.  
The signatures involving ``enable_if_convertible`` should behave
*as-if* ``enable_if_convertible`` were defined to be::

  template <bool> enable_if_convertible_impl
  {};

  template <> enable_if_convertible_impl<true>
  { struct type; };

  template<typename From, typename To>
  struct enable_if_convertible
    : enable_if_convertible_impl<is_convertible<From,To>::value>
  {};

If an expression other than the default argument is used to supply
the value of a function parameter whose type is written in terms
of ``enable_if_convertible``, the program is ill-formed, no
diagnostic required.

[*Note:* The ``enable_if_convertible`` approach uses SFINAE to
take the constructor out of the overload set when the types are not
implicitly convertible.  
]


Indirect iterator
-----------------

.. include:: indirect_iterator_abstract.rst

Class template ``pointee``
....................................

.. include:: pointee_ref.rst

Class template ``indirect_reference``
.....................................

.. include:: indirect_reference_ref.rst

Class template ``indirect_iterator``
....................................

.. include:: indirect_iterator_ref.rst

Reverse iterator
----------------

.. include:: reverse_iterator_abstract.rst

Class template ``reverse_iterator``
...................................

.. include:: reverse_iterator_ref.rst


Transform iterator
------------------

.. include:: transform_iterator_abstract.rst

Class template ``transform_iterator``
.....................................

.. include:: transform_iterator_ref.rst


Filter iterator
---------------

.. include:: filter_iterator_abstract.rst


Class template ``filter_iterator``
..................................

.. include:: filter_iterator_ref.rst


Counting iterator
-----------------

.. include:: counting_iterator_abstract.rst

Class template ``counting_iterator``
....................................

.. include:: counting_iterator_ref.rst


Function output iterator
------------------------

.. include:: func_output_iter_abstract.rst

Class template ``function_output_iterator``
...........................................

.. include:: func_output_iter_ref.rst




.. LocalWords:  Abrahams Siek Witt istream ostream iter MTL strided interoperate
   LocalWords:  CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv
   LocalWords:  GraphBase struct ptrdiff UnaryFunction const int typename bool pp
   LocalWords:  lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo
   LocalWords:  dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd
   LocalWords:  OtherIncrementable Coplien