• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:facade Iterator Facade]
2
3While the iterator interface is rich, there is a core subset of the
4interface that is necessary for all the functionality.  We have
5identified the following core behaviors for iterators:
6
7* dereferencing
8* incrementing
9* decrementing
10* equality comparison
11* random-access motion
12* distance measurement
13
14In addition to the behaviors listed above, the core interface elements
15include the associated types exposed through iterator traits:
16`value_type`, `reference`, `difference_type`, and
17`iterator_category`.
18
19Iterator facade uses the Curiously Recurring Template
20Pattern (CRTP) [Cop95]_ so that the user can specify the behavior
21of `iterator_facade` in a derived class.  Former designs used
22policy objects to specify the behavior, but that approach was
23discarded for several reasons:
24
251. the creation and eventual copying of the policy object may create
26   overhead that can be avoided with the current approach.
27
282. The policy object approach does not allow for custom constructors
29   on the created iterator types, an essential feature if
30   `iterator_facade` should be used in other library
31   implementations.
32
333. Without the use of CRTP, the standard requirement that an
34   iterator's `operator++` returns the iterator type itself
35   would mean that all iterators built with the library would
36   have to be specializations of `iterator_facade<...>`, rather
37   than something more descriptive like
38   `indirect_iterator<T*>`.  Cumbersome type generator
39   metafunctions would be needed to build new parameterized
40   iterators, and a separate `iterator_adaptor` layer would be
41   impossible.
42
43[h2 Usage]
44
45The user of `iterator_facade` derives his iterator class from a
46specialization of `iterator_facade` and passes the derived
47iterator class as `iterator_facade`\ 's first template parameter.
48The order of the other template parameters have been carefully
49chosen to take advantage of useful defaults.  For example, when
50defining a constant lvalue iterator, the user can pass a
51const-qualified version of the iterator's `value_type` as
52`iterator_facade`\ 's `Value` parameter and omit the
53`Reference` parameter which follows.
54
55The derived iterator class must define member functions implementing
56the iterator's core behaviors.  The following table describes
57expressions which are required to be valid depending on the category
58of the derived iterator type.  These member functions are described
59briefly below and in more detail in the iterator facade
60requirements.
61
62[table Core Interface
63  [
64    [Expression]
65    [Effects]
66  ]
67  [
68    [`i.dereference()`]
69    [Access the value referred to]
70  ]
71  [
72    [`i.equal(j)`]
73    [Compare for equality with `j`]
74  ]
75  [
76    [`i.increment()`]
77    [Advance by one position]
78  ]
79  [
80    [`i.decrement()`]
81    [Retreat by one position]
82  ]
83  [
84    [`i.advance(n)`]
85    [Advance by `n` positions]
86  ]
87  [
88    [`i.distance_to(j)`]
89    [Measure the distance to `j`]
90  ]
91]
92
93[/ .. Should we add a comment that a zero overhead implementation of iterator_facade is possible with proper inlining?]
94
95In addition to implementing the core interface functions, an iterator
96derived from `iterator_facade` typically defines several
97constructors. To model any of the standard iterator concepts, the
98iterator must at least have a copy constructor. Also, if the iterator
99type `X` is meant to be automatically interoperate with another
100iterator type `Y` (as with constant and mutable iterators) then
101there must be an implicit conversion from `X` to `Y` or from `Y`
102to `X` (but not both), typically implemented as a conversion
103constructor. Finally, if the iterator is to model Forward Traversal
104Iterator or a more-refined iterator concept, a default constructor is
105required.
106
107[h2 Iterator Core Access]
108
109`iterator_facade` and the operator implementations need to be able
110to access the core member functions in the derived class.  Making the
111core member functions public would expose an implementation detail to
112the user.  The design used here ensures that implementation details do
113not appear in the public interface of the derived iterator type.
114
115Preventing direct access to the core member functions has two
116advantages.  First, there is no possibility for the user to accidently
117use a member function of the iterator when a member of the value_type
118was intended.  This has been an issue with smart pointer
119implementations in the past.  The second and main advantage is that
120library implementers can freely exchange a hand-rolled iterator
121implementation for one based on `iterator_facade` without fear of
122breaking code that was accessing the public core member functions
123directly.
124
125In a naive implementation, keeping the derived class' core member
126functions private would require it to grant friendship to
127`iterator_facade` and each of the seven operators.  In order to
128reduce the burden of limiting access, `iterator_core_access` is
129provided, a class that acts as a gateway to the core member functions
130in the derived iterator class.  The author of the derived class only
131needs to grant friendship to `iterator_core_access` to make his core
132member functions available to the library.
133
134
135`iterator_core_access` will be typically implemented as an empty
136class containing only private static member functions which invoke the
137iterator core member functions. There is, however, no need to
138standardize the gateway protocol.  Note that even if
139`iterator_core_access` used public member functions it would not
140open a safety loophole, as every core member function preserves the
141invariants of the iterator.
142
143[h2 `operator[]`]
144
145The indexing operator for a generalized iterator presents special
146challenges.  A random access iterator's `operator[]` is only
147required to return something convertible to its `value_type`.
148Requiring that it return an lvalue would rule out currently-legal
149random-access iterators which hold the referenced value in a data
150member (e.g. |counting|_), because `*(p+n)` is a reference
151into the temporary iterator `p+n`, which is destroyed when
152`operator[]` returns.
153
154.. |counting| replace:: `counting_iterator`
155
156Writable iterators built with `iterator_facade` implement the
157semantics required by the preferred resolution to `issue 299`_ and
158adopted by proposal n1550_: the result of `p[n]` is an object
159convertible to the iterator's `value_type`, and `p[n] = x` is
160equivalent to `*(p + n) = x` (Note: This result object may be
161implemented as a proxy containing a copy of `p+n`).  This approach
162will work properly for any random-access iterator regardless of the
163other details of its implementation.  A user who knows more about
164the implementation of her iterator is free to implement an
165`operator[]` that returns an lvalue in the derived iterator
166class; it will hide the one supplied by `iterator_facade` from
167clients of her iterator.
168
169.. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm
170
171.. _`issue 299`: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299
172
173.. _`operator arrow`:
174
175[h2 `operator->`]
176
177The `reference` type of a readable iterator (and today's input
178iterator) need not in fact be a reference, so long as it is
179convertible to the iterator's `value_type`.  When the `value_type`
180is a class, however, it must still be possible to access members
181through `operator->`.  Therefore, an iterator whose `reference`
182type is not in fact a reference must return a proxy containing a copy
183of the referenced value from its `operator->`.
184
185The return types for `iterator_facade`\ 's `operator->` and
186`operator[]` are not explicitly specified. Instead, those types
187are described in terms of a set of requirements, which must be
188satisfied by the `iterator_facade` implementation.
189
190.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template
191   Patterns, C++ Report, February 1995, pp. 24-27.
192
193[section:facade_reference Reference]
194
195  template <
196      class Derived
197    , class Value
198    , class CategoryOrTraversal
199    , class Reference  = Value&
200    , class Difference = ptrdiff_t
201  >
202  class iterator_facade {
203   public:
204      typedef remove_const<Value>::type value_type;
205      typedef Reference reference;
206      typedef Value\* pointer;
207      typedef Difference difference_type;
208      typedef /* see below__ \*/ iterator_category;
209
210      reference operator\*() const;
211      /* see below__ \*/ operator->() const;
212      /* see below__ \*/ operator[](difference_type n) const;
213      Derived& operator++();
214      Derived operator++(int);
215      Derived& operator--();
216      Derived operator--(int);
217      Derived& operator+=(difference_type n);
218      Derived& operator-=(difference_type n);
219      Derived operator-(difference_type n) const;
220   protected:
221      typedef iterator_facade iterator_facade\_;
222  };
223
224  // Comparison operators
225  template <class Dr1, class V1, class TC1, class R1, class D1,
226            class Dr2, class V2, class TC2, class R2, class D2>
227  typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
228  operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
229              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
230
231  template <class Dr1, class V1, class TC1, class R1, class D1,
232            class Dr2, class V2, class TC2, class R2, class D2>
233  typename enable_if_interoperable<Dr1,Dr2,bool>::type
234  operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
235              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
236
237  template <class Dr1, class V1, class TC1, class R1, class D1,
238            class Dr2, class V2, class TC2, class R2, class D2>
239  typename enable_if_interoperable<Dr1,Dr2,bool>::type
240  operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
241             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
242
243  template <class Dr1, class V1, class TC1, class R1, class D1,
244            class Dr2, class V2, class TC2, class R2, class D2>
245  typename enable_if_interoperable<Dr1,Dr2,bool>::type
246  operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
247              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
248
249  template <class Dr1, class V1, class TC1, class R1, class D1,
250            class Dr2, class V2, class TC2, class R2, class D2>
251  typename enable_if_interoperable<Dr1,Dr2,bool>::type
252  operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
253             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
254
255  template <class Dr1, class V1, class TC1, class R1, class D1,
256            class Dr2, class V2, class TC2, class R2, class D2>
257  typename enable_if_interoperable<Dr1,Dr2,bool>::type
258  operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
259              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
260
261  // Iterator difference
262  template <class Dr1, class V1, class TC1, class R1, class D1,
263            class Dr2, class V2, class TC2, class R2, class D2>
264  /* see below__ \*/
265  operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
266            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
267
268  // Iterator addition
269  template <class Dr, class V, class TC, class R, class D>
270  Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
271                     typename Derived::difference_type n);
272
273  template <class Dr, class V, class TC, class R, class D>
274  Derived operator+ (typename Derived::difference_type n,
275                     iterator_facade<Dr,V,TC,R,D> const&);
276
277__ `iterator category`_
278
279__ `operator arrow`_
280
281__ brackets_
282
283__ minus_
284
285.. _`iterator category`:
286
287The `iterator_category` member of `iterator_facade` is
288
289.. parsed-literal::
290
291  *iterator-category*\ (CategoryOrTraversal, reference, value_type)
292
293where *iterator-category* is defined as follows:
294
295.. include:: facade_iterator_category.rst
296
297The `enable_if_interoperable` template used above is for exposition
298purposes.  The member operators should only be in an overload set
299provided the derived types `Dr1` and `Dr2` are interoperable,
300meaning that at least one of the types is convertible to the other.  The
301`enable_if_interoperable` approach uses SFINAE to take the operators
302out of the overload set when the types are not interoperable.
303The operators should behave *as-if* `enable_if_interoperable`
304were defined to be:
305
306  template <bool, typename> enable_if_interoperable_impl
307  {};
308
309  template <typename T> enable_if_interoperable_impl<true,T>
310  { typedef T type; };
311
312  template<typename Dr1, typename Dr2, typename T>
313  struct enable_if_interoperable
314    : enable_if_interoperable_impl<
315          is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
316        , T
317      >
318  {};
319
320
321[h2 Requirements]
322
323The following table describes the typical valid expressions on
324`iterator_facade`\ 's `Derived` parameter, depending on the
325iterator concept(s) it will model.  The operations in the first
326column must be made accessible to member functions of class
327`iterator_core_access`.  In addition,
328`static_cast<Derived*>(iterator_facade*)` shall be well-formed.
329
330In the table below, `F` is `iterator_facade<X,V,C,R,D>`, `a` is an
331object of type `X`, `b` and `c` are objects of type `const X`,
332`n` is an object of `F::difference_type`, `y` is a constant
333object of a single pass iterator type interoperable with `X`, and `z`
334is a constant object of a random access traversal iterator type
335interoperable with `X`.
336
337.. _`core operations`:
338
339.. topic:: `iterator_facade` Core Operations
340
341[table Core Operations
342  [
343    [Expression]
344    [Return Type]
345    [Assertion/Note]
346    [Used to implement Iterator Concept(s)]
347  ]
348  [
349    [`c.dereference()`]
350    [`F::reference`]
351    []
352    [Readable Iterator, Writable Iterator]
353  ]
354  [
355    [`c.equal(y)`]
356    [convertible to bool]
357    [true iff `c` and `y` refer to the same position]
358    [Single Pass Iterator]
359  ]
360  [
361    [`a.increment()`]
362    [unused]
363    []
364    [Incrementable Iterator]
365  ]
366  [
367    [`a.decrement()`]
368    [unused]
369    []
370    [Bidirectional Traversal Iterator]
371  ]
372  [
373    [`a.advance(n)`]
374    [unused]
375    []
376    [Random Access Traversal Iterator]
377  ]
378  [
379    [`c.distance_to(z)`]
380    [convertible to `F::difference_type`]
381    [equivalent to `distance(c, X(z))`.]
382    [Random Access Traversal Iterator]
383  ]
384]
385
386[h2 Operations]
387
388The operations in this section are described in terms of operations on
389the core interface of `Derived` which may be inaccessible
390(i.e. private).  The implementation should access these operations
391through member functions of class `iterator_core_access`.
392
393  reference operator*() const;
394
395[*Returns:] `static_cast<Derived const*>(this)->dereference()`
396
397  operator->() const; (see below__)
398
399__ `operator arrow`_
400
401[*Returns:] If `reference` is a reference type, an object of type `pointer` equal to: `&static_cast<Derived const*>(this)->dereference()`
402Otherwise returns an object of unspecified type such that,
403`(*static_cast<Derived const*>(this))->m` is equivalent to `(w = **static_cast<Derived const*>(this),
404w.m)` for some temporary object `w` of type `value_type`.
405
406.. _brackets:
407
408  *unspecified* operator[](difference_type n) const;
409
410[*Returns:] an object convertible to `value_type`. For constant
411     objects `v` of type `value_type`, and `n` of type
412     `difference_type`, `(*this)[n] = v` is equivalent to
413     `*(*this + n) = v`, and `static_cast<value_type
414     const&>((*this)[n])` is equivalent to
415     `static_cast<value_type const&>(*(*this + n))`
416
417  Derived& operator++();
418
419[*Effects:]
420
421    static_cast<Derived*>(this)->increment();
422    return *static_cast<Derived*>(this);
423
424  Derived operator++(int);
425
426[*Effects:]
427
428    Derived tmp(static_cast<Derived const*>(this));
429    ++*this;
430    return tmp;
431
432  Derived& operator--();
433
434[*Effects:]
435
436      static_cast<Derived*>(this)->decrement();
437      return *static_cast<Derived*>(this);
438
439  Derived operator--(int);
440
441[*Effects:]
442
443    Derived tmp(static_cast<Derived const*>(this));
444    --*this;
445    return tmp;
446
447
448  Derived& operator+=(difference_type n);
449
450[*Effects:]
451
452      static_cast<Derived*>(this)->advance(n);
453      return *static_cast<Derived*>(this);
454
455
456  Derived& operator-=(difference_type n);
457
458[*Effects:]
459
460      static_cast<Derived*>(this)->advance(-n);
461      return *static_cast<Derived*>(this);
462
463
464  Derived operator-(difference_type n) const;
465
466[*Effects:]
467
468    Derived tmp(static_cast<Derived const*>(this));
469    return tmp -= n;
470
471  template <class Dr, class V, class TC, class R, class D>
472  Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
473                     typename Derived::difference_type n);
474
475  template <class Dr, class V, class TC, class R, class D>
476  Derived operator+ (typename Derived::difference_type n,
477                     iterator_facade<Dr,V,TC,R,D> const&);
478
479[*Effects:]
480
481    Derived tmp(static_cast<Derived const*>(this));
482    return tmp += n;
483
484  template <class Dr1, class V1, class TC1, class R1, class D1,
485            class Dr2, class V2, class TC2, class R2, class D2>
486  typename enable_if_interoperable<Dr1,Dr2,bool>::type
487  operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
488              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
489
490[*Returns:]
491
492[pre
493  if `is_convertible<Dr2,Dr1>::value`
494
495  then
496    `((Dr1 const&)lhs).equal((Dr2 const&)rhs)`.
497
498  Otherwise,
499    `((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
500]
501
502
503  template <class Dr1, class V1, class TC1, class R1, class D1,
504            class Dr2, class V2, class TC2, class R2, class D2>
505  typename enable_if_interoperable<Dr1,Dr2,bool>::type
506  operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
507              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
508
509[*Returns:]
510
511[pre
512  if `is_convertible<Dr2,Dr1>::value`
513
514  then
515    `!((Dr1 const&)lhs).equal((Dr2 const&)rhs)`.
516
517  Otherwise,
518    `!((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
519]
520
521
522  template <class Dr1, class V1, class TC1, class R1, class D1,
523            class Dr2, class V2, class TC2, class R2, class D2>
524  typename enable_if_interoperable<Dr1,Dr2,bool>::type
525  operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
526             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
527
528[*Returns:]
529
530[pre
531  if `is_convertible<Dr2,Dr1>::value`
532
533  then
534    `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0`.
535
536  Otherwise,
537    `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0`.
538]
539
540
541  template <class Dr1, class V1, class TC1, class R1, class D1,
542            class Dr2, class V2, class TC2, class R2, class D2>
543  typename enable_if_interoperable<Dr1,Dr2,bool>::type
544  operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
545              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
546
547[*Returns:]
548
549[pre
550  if `is_convertible<Dr2,Dr1>::value`
551
552  then
553    `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0`.
554
555  Otherwise,
556    `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0`.
557]
558
559
560  template <class Dr1, class V1, class TC1, class R1, class D1,
561            class Dr2, class V2, class TC2, class R2, class D2>
562  typename enable_if_interoperable<Dr1,Dr2,bool>::type
563  operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
564             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
565
566[*Returns:]
567
568[pre
569  if `is_convertible<Dr2,Dr1>::value`
570
571  then
572    `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0`.
573
574  Otherwise,
575    `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0`.
576]
577
578
579  template <class Dr1, class V1, class TC1, class R1, class D1,
580            class Dr2, class V2, class TC2, class R2, class D2>
581  typename enable_if_interoperable<Dr1,Dr2,bool>::type
582  operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
583              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
584
585[*Returns:]
586
587[pre
588  if `is_convertible<Dr2,Dr1>::value`
589
590  then
591    `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0`.
592
593  Otherwise,
594    `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0`.
595]
596
597.. _minus:
598
599
600  template <class Dr1, class V1, class TC1, class R1, class D1,
601            class Dr2, class V2, class TC2, class R2, class D2>
602  typename enable_if_interoperable<Dr1,Dr2,difference>::type
603  operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
604             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
605
606[*Return Type:]
607
608[pre
609  if `is_convertible<Dr2,Dr1>::value`
610
611   then
612    `difference` shall be
613    `iterator_traits<Dr1>::difference_type`.
614
615   Otherwise
616    `difference` shall be `iterator_traits<Dr2>::difference_type`
617]
618
619[*Returns:]
620
621[pre
622  if `is_convertible<Dr2,Dr1>::value`
623
624  then
625    `-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)`.
626
627  Otherwise,
628    `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)`.
629]
630
631
632[endsect]
633
634[include facade_tutorial.qbk]
635
636[endsect]
637