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)
5 .. Version 1.3 of this ReStructuredText document corresponds to
6 n1530_, the paper accepted by the LWG for TR1.
8 .. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
16 , class CategoryOrTraversal
17 , class Reference = Value&
18 , class Difference = ptrdiff_t
20 class iterator_facade {
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;
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;
39 typedef iterator_facade iterator_facade\_;
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);
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);
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);
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);
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);
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);
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>
83 operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
84 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
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);
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&);
95 __ `iterator category`_
103 .. _`iterator category`:
105 The ``iterator_category`` member of ``iterator_facade`` is
109 *iterator-category*\ (CategoryOrTraversal, reference, value_type)
111 where *iterator-category* is defined as follows:
113 .. include:: facade_iterator_category.rst
115 The ``enable_if_interoperable`` template used above is for exposition
116 purposes. The member operators should only be in an overload set
117 provided the derived types ``Dr1`` and ``Dr2`` are interoperable,
118 meaning that at least one of the types is convertible to the other. The
119 ``enable_if_interoperable`` approach uses SFINAE to take the operators
120 out of the overload set when the types are not interoperable.
121 The operators should behave *as-if* ``enable_if_interoperable``
124 template <bool, typename> enable_if_interoperable_impl
127 template <typename T> enable_if_interoperable_impl<true,T>
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
139 ``iterator_facade`` Requirements
140 --------------------------------
142 The following table describes the typical valid expressions on
143 ``iterator_facade``\ 's ``Derived`` parameter, depending on the
144 iterator concept(s) it will model. The operations in the first
145 column 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.
149 In the table below, ``F`` is ``iterator_facade<X,V,C,R,D>``, ``a`` is an
150 object 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
152 object of a single pass iterator type interoperable with ``X``, and ``z``
153 is a constant object of a random access traversal iterator type
154 interoperable with ``X``.
156 .. _`core operations`:
158 .. topic:: ``iterator_facade`` Core Operations
160 +--------------------+----------------------+-------------------------+---------------------------+
161 |Expression |Return Type |Assertion/Note |Used to implement Iterator |
163 +====================+======================+=========================+===========================+
164 |``c.dereference()`` |``F::reference`` | |Readable Iterator, Writable|
166 +--------------------+----------------------+-------------------------+---------------------------+
167 |``c.equal(y)`` |convertible to bool |true iff ``c`` and ``y`` |Single Pass Iterator |
168 | | |refer to the same | |
170 +--------------------+----------------------+-------------------------+---------------------------+
171 |``a.increment()`` |unused | |Incrementable Iterator |
172 +--------------------+----------------------+-------------------------+---------------------------+
173 |``a.decrement()`` |unused | |Bidirectional Traversal |
175 +--------------------+----------------------+-------------------------+---------------------------+
176 |``a.advance(n)`` |unused | |Random Access Traversal |
178 +--------------------+----------------------+-------------------------+---------------------------+
179 |``c.distance_to(z)``|convertible to |equivalent to |Random Access Traversal |
180 | |``F::difference_type``|``distance(c, X(z))``. |Iterator |
181 +--------------------+----------------------+-------------------------+---------------------------+
185 ``iterator_facade`` operations
186 ------------------------------
188 The operations in this section are described in terms of operations on
189 the core interface of ``Derived`` which may be inaccessible
190 (i.e. private). The implementation should access these operations
191 through member functions of class ``iterator_core_access``.
193 ``reference operator*() const;``
195 :Returns: ``static_cast<Derived const*>(this)->dereference()``
197 ``operator->() const;`` (see below__)
201 :Returns: If ``reference`` is a reference type, an object
202 of type ``pointer`` equal to::
204 &static_cast<Derived const*>(this)->dereference()
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``.
212 *unspecified* ``operator[](difference_type n) const;``
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))``
223 ``Derived& operator++();``
229 static_cast<Derived*>(this)->increment();
230 return *static_cast<Derived*>(this);
232 ``Derived operator++(int);``
238 Derived tmp(static_cast<Derived const*>(this));
243 ``Derived& operator--();``
249 static_cast<Derived*>(this)->decrement();
250 return *static_cast<Derived*>(this);
253 ``Derived operator--(int);``
259 Derived tmp(static_cast<Derived const*>(this));
264 ``Derived& operator+=(difference_type n);``
270 static_cast<Derived*>(this)->advance(n);
271 return *static_cast<Derived*>(this);
274 ``Derived& operator-=(difference_type n);``
280 static_cast<Derived*>(this)->advance(-n);
281 return *static_cast<Derived*>(this);
284 ``Derived operator-(difference_type n) const;``
290 Derived tmp(static_cast<Derived const*>(this));
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);
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&);
307 Derived tmp(static_cast<Derived const*>(this));
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);
320 if ``is_convertible<Dr2,Dr1>::value``
323 ``((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
326 ``((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
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);
337 if ``is_convertible<Dr2,Dr1>::value``
340 ``!((Dr1 const&)lhs).equal((Dr2 const&)rhs)``.
343 ``!((Dr2 const&)rhs).equal((Dr1 const&)lhs)``.
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);
354 if ``is_convertible<Dr2,Dr1>::value``
357 ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0``.
360 ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0``.
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);
371 if ``is_convertible<Dr2,Dr1>::value``
374 ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0``.
377 ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0``.
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);
388 if ``is_convertible<Dr2,Dr1>::value``
391 ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0``.
394 ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0``.
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);
406 if ``is_convertible<Dr2,Dr1>::value``
409 ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0``.
412 ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0``.
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);
425 if ``is_convertible<Dr2,Dr1>::value``
428 ``difference`` shall be
429 ``iterator_traits<Dr1>::difference_type``.
432 ``difference`` shall be ``iterator_traits<Dr2>::difference_type``
435 if ``is_convertible<Dr2,Dr1>::value``
438 ``-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)``.
441 ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)``.