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.. Version 1.3 of this ReStructuredText document corresponds to
6   n1530_, the paper accepted by the LWG for TR1.
7
8.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
9
10
11.. parsed-literal::
12
13  template <
14      class Derived
15    , class Value
16    , class CategoryOrTraversal
17    , class Reference  = Value&
18    , class Difference = ptrdiff_t
19  >
20  class iterator_facade {
21   public:
22      typedef remove_const<Value>::type value_type;
23      typedef Reference reference;
24      typedef Value\* pointer;
25      typedef Difference difference_type;
26      typedef /* see below__ \*/ iterator_category;
27
28      reference operator\*() const;
29      /* see below__ \*/ operator->() const;
30      /* see below__ \*/ operator[](difference_type n) const;
31      Derived& operator++();
32      Derived operator++(int);
33      Derived& operator--();
34      Derived operator--(int);
35      Derived& operator+=(difference_type n);
36      Derived& operator-=(difference_type n);
37      Derived operator-(difference_type n) const;
38   protected:
39      typedef iterator_facade iterator_facade\_;
40  };
41
42  // Comparison operators
43  template <class Dr1, class V1, class TC1, class R1, class D1,
44            class Dr2, class V2, class TC2, class R2, class D2>
45  typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
46  operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
47              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
48
49  template <class Dr1, class V1, class TC1, class R1, class D1,
50            class Dr2, class V2, class TC2, class R2, class D2>
51  typename enable_if_interoperable<Dr1,Dr2,bool>::type
52  operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
53              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
54
55  template <class Dr1, class V1, class TC1, class R1, class D1,
56            class Dr2, class V2, class TC2, class R2, class D2>
57  typename enable_if_interoperable<Dr1,Dr2,bool>::type
58  operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
59             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
60
61  template <class Dr1, class V1, class TC1, class R1, class D1,
62            class Dr2, class V2, class TC2, class R2, class D2>
63  typename enable_if_interoperable<Dr1,Dr2,bool>::type
64  operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
65              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
66
67  template <class Dr1, class V1, class TC1, class R1, class D1,
68            class Dr2, class V2, class TC2, class R2, class D2>
69  typename enable_if_interoperable<Dr1,Dr2,bool>::type
70  operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
71             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
72
73  template <class Dr1, class V1, class TC1, class R1, class D1,
74            class Dr2, class V2, class TC2, class R2, class D2>
75  typename enable_if_interoperable<Dr1,Dr2,bool>::type
76  operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
77              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
78
79  // Iterator difference
80  template <class Dr1, class V1, class TC1, class R1, class D1,
81            class Dr2, class V2, class TC2, class R2, class D2>
82  /* see below__ \*/
83  operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
84            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
85
86  // Iterator addition
87  template <class Dr, class V, class TC, class R, class D>
88  Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
89                     typename Derived::difference_type n);
90
91  template <class Dr, class V, class TC, class R, class D>
92  Derived operator+ (typename Derived::difference_type n,
93                     iterator_facade<Dr,V,TC,R,D> const&);
94
95__ `iterator category`_
96
97__ `operator arrow`_
98
99__ brackets_
100
101__ minus_
102
103.. _`iterator category`:
104
105The ``iterator_category`` member of ``iterator_facade`` is
106
107.. parsed-literal::
108
109  *iterator-category*\ (CategoryOrTraversal, reference, value_type)
110
111where *iterator-category* is defined as follows:
112
113.. include:: facade_iterator_category.rst
114
115The ``enable_if_interoperable`` template used above is for exposition
116purposes.  The member operators should only be in an overload set
117provided the derived types ``Dr1`` and ``Dr2`` are interoperable,
118meaning that at least one of the types is convertible to the other.  The
119``enable_if_interoperable`` approach uses SFINAE to take the operators
120out of the overload set when the types are not interoperable.
121The operators should behave *as-if* ``enable_if_interoperable``
122were defined to be::
123
124  template <bool, typename> enable_if_interoperable_impl
125  {};
126
127  template <typename T> enable_if_interoperable_impl<true,T>
128  { typedef T type; };
129
130  template<typename Dr1, typename Dr2, typename T>
131  struct enable_if_interoperable
132    : enable_if_interoperable_impl<
133          is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
134        , T
135      >
136  {};
137
138
139``iterator_facade`` Requirements
140--------------------------------
141
142The following table describes the typical valid expressions on
143``iterator_facade``\ 's ``Derived`` parameter, depending on the
144iterator concept(s) it will model.  The operations in the first
145column must be made accessible to member functions of class
146``iterator_core_access``.  In addition,
147``static_cast<Derived*>(iterator_facade*)`` shall be well-formed.
148
149In the table below, ``F`` is ``iterator_facade<X,V,C,R,D>``, ``a`` is an
150object of type ``X``, ``b`` and ``c`` are objects of type ``const X``,
151``n`` is an object of ``F::difference_type``, ``y`` is a constant
152object of a single pass iterator type interoperable with ``X``, and ``z``
153is a constant object of a random access traversal iterator type
154interoperable with ``X``.
155
156.. _`core operations`:
157
158.. topic:: ``iterator_facade`` Core Operations
159
160   +--------------------+----------------------+-------------------------+---------------------------+
161   |Expression          |Return Type           |Assertion/Note           |Used to implement Iterator |
162   |                    |                      |                         |Concept(s)                 |
163   +====================+======================+=========================+===========================+
164   |``c.dereference()`` |``F::reference``      |                         |Readable Iterator, Writable|
165   |                    |                      |                         |Iterator                   |
166   +--------------------+----------------------+-------------------------+---------------------------+
167   |``c.equal(y)``      |convertible to bool   |true iff ``c`` and ``y`` |Single Pass Iterator       |
168   |                    |                      |refer to the same        |                           |
169   |                    |                      |position.                |                           |
170   +--------------------+----------------------+-------------------------+---------------------------+
171   |``a.increment()``   |unused                |                         |Incrementable Iterator     |
172   +--------------------+----------------------+-------------------------+---------------------------+
173   |``a.decrement()``   |unused                |                         |Bidirectional Traversal    |
174   |                    |                      |                         |Iterator                   |
175   +--------------------+----------------------+-------------------------+---------------------------+
176   |``a.advance(n)``    |unused                |                         |Random Access Traversal    |
177   |                    |                      |                         |Iterator                   |
178   +--------------------+----------------------+-------------------------+---------------------------+
179   |``c.distance_to(z)``|convertible to        |equivalent to            |Random Access Traversal    |
180   |                    |``F::difference_type``|``distance(c, X(z))``.   |Iterator                   |
181   +--------------------+----------------------+-------------------------+---------------------------+
182
183
184
185``iterator_facade`` operations
186------------------------------
187
188The operations in this section are described in terms of operations on
189the core interface of ``Derived`` which may be inaccessible
190(i.e. private).  The implementation should access these operations
191through member functions of class ``iterator_core_access``.
192
193``reference operator*() const;``
194
195:Returns: ``static_cast<Derived const*>(this)->dereference()``
196
197``operator->() const;`` (see below__)
198
199__ `operator arrow`_
200
201:Returns: If ``reference`` is a reference type, an object
202  of type ``pointer`` equal to::
203
204    &static_cast<Derived const*>(this)->dereference()
205
206  Otherwise returns an object of unspecified type such that,
207  ``(*static_cast<Derived const*>(this))->m`` is equivalent to ``(w = **static_cast<Derived const*>(this),
208  w.m)`` for some temporary object ``w`` of type ``value_type``.
209
210.. _brackets:
211
212*unspecified* ``operator[](difference_type n) const;``
213
214:Returns: an object convertible to ``value_type``. For constant
215     objects ``v`` of type ``value_type``, and ``n`` of type
216     ``difference_type``, ``(*this)[n] = v`` is equivalent to
217     ``*(*this + n) = v``, and ``static_cast<value_type
218     const&>((*this)[n])`` is equivalent to
219     ``static_cast<value_type const&>(*(*this + n))``
220
221
222
223``Derived& operator++();``
224
225:Effects:
226
227  ::
228
229    static_cast<Derived*>(this)->increment();
230    return *static_cast<Derived*>(this);
231
232``Derived operator++(int);``
233
234:Effects:
235
236  ::
237
238    Derived tmp(static_cast<Derived const*>(this));
239    ++*this;
240    return tmp;
241
242
243``Derived& operator--();``
244
245:Effects:
246
247   ::
248
249      static_cast<Derived*>(this)->decrement();
250      return *static_cast<Derived*>(this);
251
252
253``Derived operator--(int);``
254
255:Effects:
256
257  ::
258
259    Derived tmp(static_cast<Derived const*>(this));
260    --*this;
261    return tmp;
262
263
264``Derived& operator+=(difference_type n);``
265
266:Effects:
267
268  ::
269
270      static_cast<Derived*>(this)->advance(n);
271      return *static_cast<Derived*>(this);
272
273
274``Derived& operator-=(difference_type n);``
275
276:Effects:
277
278  ::
279
280      static_cast<Derived*>(this)->advance(-n);
281      return *static_cast<Derived*>(this);
282
283
284``Derived operator-(difference_type n) const;``
285
286:Effects:
287
288  ::
289
290    Derived tmp(static_cast<Derived const*>(this));
291    return tmp -= n;
292
293::
294
295  template <class Dr, class V, class TC, class R, class D>
296  Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
297                     typename Derived::difference_type n);
298
299  template <class Dr, class V, class TC, class R, class D>
300  Derived operator+ (typename Derived::difference_type n,
301                     iterator_facade<Dr,V,TC,R,D> const&);
302
303:Effects:
304
305  ::
306
307    Derived tmp(static_cast<Derived const*>(this));
308    return tmp += n;
309
310
311::
312
313  template <class Dr1, class V1, class TC1, class R1, class D1,
314            class Dr2, class V2, class TC2, class R2, class D2>
315  typename enable_if_interoperable<Dr1,Dr2,bool>::type
316  operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
317              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
318
319:Returns:
320  if ``is_convertible<Dr2,Dr1>::value``
321
322  then
323    ``((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
324
325  Otherwise,
326    ``((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
327
328::
329
330  template <class Dr1, class V1, class TC1, class R1, class D1,
331            class Dr2, class V2, class TC2, class R2, class D2>
332  typename enable_if_interoperable<Dr1,Dr2,bool>::type
333  operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
334              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
335
336:Returns:
337  if ``is_convertible<Dr2,Dr1>::value``
338
339  then
340    ``!((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
341
342  Otherwise,
343    ``!((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
344
345::
346
347  template <class Dr1, class V1, class TC1, class R1, class D1,
348            class Dr2, class V2, class TC2, class R2, class D2>
349  typename enable_if_interoperable<Dr1,Dr2,bool>::type
350  operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
351             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
352
353:Returns:
354  if ``is_convertible<Dr2,Dr1>::value``
355
356  then
357    ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0``.
358
359  Otherwise,
360    ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0``.
361
362::
363
364  template <class Dr1, class V1, class TC1, class R1, class D1,
365            class Dr2, class V2, class TC2, class R2, class D2>
366  typename enable_if_interoperable<Dr1,Dr2,bool>::type
367  operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
368              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
369
370:Returns:
371  if ``is_convertible<Dr2,Dr1>::value``
372
373  then
374    ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0``.
375
376  Otherwise,
377    ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0``.
378
379::
380
381  template <class Dr1, class V1, class TC1, class R1, class D1,
382            class Dr2, class V2, class TC2, class R2, class D2>
383  typename enable_if_interoperable<Dr1,Dr2,bool>::type
384  operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
385             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
386
387:Returns:
388  if ``is_convertible<Dr2,Dr1>::value``
389
390  then
391    ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0``.
392
393  Otherwise,
394    ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0``.
395
396
397::
398
399  template <class Dr1, class V1, class TC1, class R1, class D1,
400            class Dr2, class V2, class TC2, class R2, class D2>
401  typename enable_if_interoperable<Dr1,Dr2,bool>::type
402  operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
403              iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
404
405:Returns:
406  if ``is_convertible<Dr2,Dr1>::value``
407
408  then
409    ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0``.
410
411  Otherwise,
412    ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0``.
413
414.. _minus:
415
416::
417
418  template <class Dr1, class V1, class TC1, class R1, class D1,
419            class Dr2, class V2, class TC2, class R2, class D2>
420  typename enable_if_interoperable<Dr1,Dr2,difference>::type
421  operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
422             iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
423
424:Return Type:
425  if ``is_convertible<Dr2,Dr1>::value``
426
427   then
428    ``difference`` shall be
429    ``iterator_traits<Dr1>::difference_type``.
430
431   Otherwise
432    ``difference`` shall be ``iterator_traits<Dr2>::difference_type``
433
434:Returns:
435  if ``is_convertible<Dr2,Dr1>::value``
436
437  then
438    ``-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)``.
439
440  Otherwise,
441    ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)``.
442