2 [section:facade Iterator Facade]
4 While the iterator interface is rich, there is a core subset of the
5 interface that is necessary for all the functionality. We have
6 identified the following core behaviors for iterators:
12 * random-access motion
13 * distance measurement
15 In addition to the behaviors listed above, the core interface elements
16 include the associated types exposed through iterator traits:
17 `value_type`, `reference`, `difference_type`, and
20 Iterator facade uses the Curiously Recurring Template
21 Pattern (CRTP) [Cop95]_ so that the user can specify the behavior
22 of `iterator_facade` in a derived class. Former designs used
23 policy objects to specify the behavior, but that approach was
24 discarded for several reasons:
26 1. the creation and eventual copying of the policy object may create
27 overhead that can be avoided with the current approach.
29 2. The policy object approach does not allow for custom constructors
30 on the created iterator types, an essential feature if
31 `iterator_facade` should be used in other library
34 3. Without the use of CRTP, the standard requirement that an
35 iterator's `operator++` returns the iterator type itself
36 would mean that all iterators built with the library would
37 have to be specializations of `iterator_facade<...>`, rather
38 than something more descriptive like
39 `indirect_iterator<T*>`. Cumbersome type generator
40 metafunctions would be needed to build new parameterized
41 iterators, and a separate `iterator_adaptor` layer would be
46 The user of `iterator_facade` derives his iterator class from a
47 specialization of `iterator_facade` and passes the derived
48 iterator class as `iterator_facade`\ 's first template parameter.
49 The order of the other template parameters have been carefully
50 chosen to take advantage of useful defaults. For example, when
51 defining a constant lvalue iterator, the user can pass a
52 const-qualified version of the iterator's `value_type` as
53 `iterator_facade`\ 's `Value` parameter and omit the
54 `Reference` parameter which follows.
56 The derived iterator class must define member functions implementing
57 the iterator's core behaviors. The following table describes
58 expressions which are required to be valid depending on the category
59 of the derived iterator type. These member functions are described
60 briefly below and in more detail in the iterator facade
70 [Access the value referred to]
74 [Compare for equality with `j`]
78 [Advance by one position]
82 [Retreat by one position]
86 [Advance by `n` positions]
90 [Measure the distance to `j`]
94 [/ .. Should we add a comment that a zero overhead implementation of iterator_facade is possible with proper inlining?]
96 In addition to implementing the core interface functions, an iterator
97 derived from `iterator_facade` typically defines several
98 constructors. To model any of the standard iterator concepts, the
99 iterator must at least have a copy constructor. Also, if the iterator
100 type `X` is meant to be automatically interoperate with another
101 iterator type `Y` (as with constant and mutable iterators) then
102 there must be an implicit conversion from `X` to `Y` or from `Y`
103 to `X` (but not both), typically implemented as a conversion
104 constructor. Finally, if the iterator is to model Forward Traversal
105 Iterator or a more-refined iterator concept, a default constructor is
108 [h2 Iterator Core Access]
110 `iterator_facade` and the operator implementations need to be able
111 to access the core member functions in the derived class. Making the
112 core member functions public would expose an implementation detail to
113 the user. The design used here ensures that implementation details do
114 not appear in the public interface of the derived iterator type.
116 Preventing direct access to the core member functions has two
117 advantages. First, there is no possibility for the user to accidently
118 use a member function of the iterator when a member of the value_type
119 was intended. This has been an issue with smart pointer
120 implementations in the past. The second and main advantage is that
121 library implementers can freely exchange a hand-rolled iterator
122 implementation for one based on `iterator_facade` without fear of
123 breaking code that was accessing the public core member functions
126 In a naive implementation, keeping the derived class' core member
127 functions private would require it to grant friendship to
128 `iterator_facade` and each of the seven operators. In order to
129 reduce the burden of limiting access, `iterator_core_access` is
130 provided, a class that acts as a gateway to the core member functions
131 in the derived iterator class. The author of the derived class only
132 needs to grant friendship to `iterator_core_access` to make his core
133 member functions available to the library.
136 `iterator_core_access` will be typically implemented as an empty
137 class containing only private static member functions which invoke the
138 iterator core member functions. There is, however, no need to
139 standardize the gateway protocol. Note that even if
140 `iterator_core_access` used public member functions it would not
141 open a safety loophole, as every core member function preserves the
142 invariants of the iterator.
146 The indexing operator for a generalized iterator presents special
147 challenges. A random access iterator's `operator[]` is only
148 required to return something convertible to its `value_type`.
149 Requiring that it return an lvalue would rule out currently-legal
150 random-access iterators which hold the referenced value in a data
151 member (e.g. |counting|_), because `*(p+n)` is a reference
152 into the temporary iterator `p+n`, which is destroyed when
153 `operator[]` returns.
155 .. |counting| replace:: `counting_iterator`
157 Writable iterators built with `iterator_facade` implement the
158 semantics required by the preferred resolution to `issue 299`_ and
159 adopted by proposal n1550_: the result of `p[n]` is an object
160 convertible to the iterator's `value_type`, and `p[n] = x` is
161 equivalent to `*(p + n) = x` (Note: This result object may be
162 implemented as a proxy containing a copy of `p+n`). This approach
163 will work properly for any random-access iterator regardless of the
164 other details of its implementation. A user who knows more about
165 the implementation of her iterator is free to implement an
166 `operator[]` that returns an lvalue in the derived iterator
167 class; it will hide the one supplied by `iterator_facade` from
168 clients of her iterator.
170 .. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm
172 .. _`issue 299`: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299
174 .. _`operator arrow`:
178 The `reference` type of a readable iterator (and today's input
179 iterator) need not in fact be a reference, so long as it is
180 convertible to the iterator's `value_type`. When the `value_type`
181 is a class, however, it must still be possible to access members
182 through `operator->`. Therefore, an iterator whose `reference`
183 type is not in fact a reference must return a proxy containing a copy
184 of the referenced value from its `operator->`.
186 The return types for `iterator_facade`\ 's `operator->` and
187 `operator[]` are not explicitly specified. Instead, those types
188 are described in terms of a set of requirements, which must be
189 satisfied by the `iterator_facade` implementation.
191 .. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template
192 Patterns, C++ Report, February 1995, pp. 24-27.
194 [section:facade_reference Reference]
199 , class CategoryOrTraversal
200 , class Reference = Value&
201 , class Difference = ptrdiff_t
203 class iterator_facade {
205 typedef remove_const<Value>::type value_type;
206 typedef Reference reference;
207 typedef Value\* pointer;
208 typedef Difference difference_type;
209 typedef /* see below__ \*/ iterator_category;
211 reference operator\*() const;
212 /* see below__ \*/ operator->() const;
213 /* see below__ \*/ operator[](difference_type n) const;
214 Derived& operator++();
215 Derived operator++(int);
216 Derived& operator--();
217 Derived operator--(int);
218 Derived& operator+=(difference_type n);
219 Derived& operator-=(difference_type n);
220 Derived operator-(difference_type n) const;
222 typedef iterator_facade iterator_facade\_;
225 // Comparison operators
226 template <class Dr1, class V1, class TC1, class R1, class D1,
227 class Dr2, class V2, class TC2, class R2, class D2>
228 typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
229 operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
230 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
232 template <class Dr1, class V1, class TC1, class R1, class D1,
233 class Dr2, class V2, class TC2, class R2, class D2>
234 typename enable_if_interoperable<Dr1,Dr2,bool>::type
235 operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
236 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
238 template <class Dr1, class V1, class TC1, class R1, class D1,
239 class Dr2, class V2, class TC2, class R2, class D2>
240 typename enable_if_interoperable<Dr1,Dr2,bool>::type
241 operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
242 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
244 template <class Dr1, class V1, class TC1, class R1, class D1,
245 class Dr2, class V2, class TC2, class R2, class D2>
246 typename enable_if_interoperable<Dr1,Dr2,bool>::type
247 operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
248 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
250 template <class Dr1, class V1, class TC1, class R1, class D1,
251 class Dr2, class V2, class TC2, class R2, class D2>
252 typename enable_if_interoperable<Dr1,Dr2,bool>::type
253 operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
254 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
256 template <class Dr1, class V1, class TC1, class R1, class D1,
257 class Dr2, class V2, class TC2, class R2, class D2>
258 typename enable_if_interoperable<Dr1,Dr2,bool>::type
259 operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
260 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
262 // Iterator difference
263 template <class Dr1, class V1, class TC1, class R1, class D1,
264 class Dr2, class V2, class TC2, class R2, class D2>
266 operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
267 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
270 template <class Dr, class V, class TC, class R, class D>
271 Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
272 typename Derived::difference_type n);
274 template <class Dr, class V, class TC, class R, class D>
275 Derived operator+ (typename Derived::difference_type n,
276 iterator_facade<Dr,V,TC,R,D> const&);
278 __ `iterator category`_
286 .. _`iterator category`:
288 The `iterator_category` member of `iterator_facade` is
292 *iterator-category*\ (CategoryOrTraversal, value_type, reference)
294 where *iterator-category* is defined as follows:
296 .. include:: facade_iterator_category.rst
298 The `enable_if_interoperable` template used above is for exposition
299 purposes. The member operators should only be in an overload set
300 provided the derived types `Dr1` and `Dr2` are interoperable,
301 meaning that at least one of the types is convertible to the other. The
302 `enable_if_interoperable` approach uses SFINAE to take the operators
303 out of the overload set when the types are not interoperable.
304 The operators should behave *as-if* `enable_if_interoperable`
307 template <bool, typename> enable_if_interoperable_impl
310 template <typename T> enable_if_interoperable_impl<true,T>
313 template<typename Dr1, typename Dr2, typename T>
314 struct enable_if_interoperable
315 : enable_if_interoperable_impl<
316 is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
324 The following table describes the typical valid expressions on
325 `iterator_facade`\ 's `Derived` parameter, depending on the
326 iterator concept(s) it will model. The operations in the first
327 column must be made accessible to member functions of class
328 `iterator_core_access`. In addition,
329 `static_cast<Derived*>(iterator_facade*)` shall be well-formed.
331 In the table below, `F` is `iterator_facade<X,V,C,R,D>`, `a` is an
332 object of type `X`, `b` and `c` are objects of type `const X`,
333 `n` is an object of `F::difference_type`, `y` is a constant
334 object of a single pass iterator type interoperable with `X`, and `z`
335 is a constant object of a random access traversal iterator type
336 interoperable with `X`.
338 .. _`core operations`:
340 .. topic:: `iterator_facade` Core Operations
342 [table Core Operations
347 [Used to implement Iterator Concept(s)]
353 [Readable Iterator, Writable Iterator]
357 [convertible to bool]
358 [true iff `c` and `y` refer to the same position]
359 [Single Pass Iterator]
365 [Incrementable Iterator]
371 [Bidirectional Traversal Iterator]
377 [Random Access Traversal Iterator]
381 [convertible to `F::difference_type`]
382 [equivalent to `distance(c, X(z))`.]
383 [Random Access Traversal Iterator]
389 The operations in this section are described in terms of operations on
390 the core interface of `Derived` which may be inaccessible
391 (i.e. private). The implementation should access these operations
392 through member functions of class `iterator_core_access`.
394 reference operator*() const;
396 [*Returns:] `static_cast<Derived const*>(this)->dereference()`
398 operator->() const; (see below__)
402 [*Returns:] If `reference` is a reference type, an object of type `pointer` equal to: `&static_cast<Derived const*>(this)->dereference()`
403 Otherwise returns an object of unspecified type such that,
404 `(*static_cast<Derived const*>(this))->m` is equivalent to `(w = **static_cast<Derived const*>(this),
405 w.m)` for some temporary object `w` of type `value_type`.
409 *unspecified* operator[](difference_type n) const;
411 [*Returns:] an object convertible to `value_type`. For constant
412 objects `v` of type `value_type`, and `n` of type
413 `difference_type`, `(*this)[n] = v` is equivalent to
414 `*(*this + n) = v`, and `static_cast<value_type
415 const&>((*this)[n])` is equivalent to
416 `static_cast<value_type const&>(*(*this + n))`
418 Derived& operator++();
422 static_cast<Derived*>(this)->increment();
423 return *static_cast<Derived*>(this);
425 Derived operator++(int);
429 Derived tmp(static_cast<Derived const*>(this));
433 Derived& operator--();
437 static_cast<Derived*>(this)->decrement();
438 return *static_cast<Derived*>(this);
440 Derived operator--(int);
444 Derived tmp(static_cast<Derived const*>(this));
449 Derived& operator+=(difference_type n);
453 static_cast<Derived*>(this)->advance(n);
454 return *static_cast<Derived*>(this);
457 Derived& operator-=(difference_type n);
461 static_cast<Derived*>(this)->advance(-n);
462 return *static_cast<Derived*>(this);
465 Derived operator-(difference_type n) const;
469 Derived tmp(static_cast<Derived const*>(this));
472 template <class Dr, class V, class TC, class R, class D>
473 Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
474 typename Derived::difference_type n);
476 template <class Dr, class V, class TC, class R, class D>
477 Derived operator+ (typename Derived::difference_type n,
478 iterator_facade<Dr,V,TC,R,D> const&);
482 Derived tmp(static_cast<Derived const*>(this));
485 template <class Dr1, class V1, class TC1, class R1, class D1,
486 class Dr2, class V2, class TC2, class R2, class D2>
487 typename enable_if_interoperable<Dr1,Dr2,bool>::type
488 operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
489 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
494 if `is_convertible<Dr2,Dr1>::value`
497 `((Dr1 const&)lhs).equal((Dr2 const&)rhs)`.
500 `((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
504 template <class Dr1, class V1, class TC1, class R1, class D1,
505 class Dr2, class V2, class TC2, class R2, class D2>
506 typename enable_if_interoperable<Dr1,Dr2,bool>::type
507 operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
508 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
513 if `is_convertible<Dr2,Dr1>::value`
516 `!((Dr1 const&)lhs).equal((Dr2 const&)rhs)`.
519 `!((Dr2 const&)rhs).equal((Dr1 const&)lhs)`.
523 template <class Dr1, class V1, class TC1, class R1, class D1,
524 class Dr2, class V2, class TC2, class R2, class D2>
525 typename enable_if_interoperable<Dr1,Dr2,bool>::type
526 operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
527 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
532 if `is_convertible<Dr2,Dr1>::value`
535 `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0`.
538 `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0`.
542 template <class Dr1, class V1, class TC1, class R1, class D1,
543 class Dr2, class V2, class TC2, class R2, class D2>
544 typename enable_if_interoperable<Dr1,Dr2,bool>::type
545 operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
546 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
551 if `is_convertible<Dr2,Dr1>::value`
554 `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0`.
557 `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0`.
561 template <class Dr1, class V1, class TC1, class R1, class D1,
562 class Dr2, class V2, class TC2, class R2, class D2>
563 typename enable_if_interoperable<Dr1,Dr2,bool>::type
564 operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
565 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
570 if `is_convertible<Dr2,Dr1>::value`
573 `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0`.
576 `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0`.
580 template <class Dr1, class V1, class TC1, class R1, class D1,
581 class Dr2, class V2, class TC2, class R2, class D2>
582 typename enable_if_interoperable<Dr1,Dr2,bool>::type
583 operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
584 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
589 if `is_convertible<Dr2,Dr1>::value`
592 `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0`.
595 `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0`.
601 template <class Dr1, class V1, class TC1, class R1, class D1,
602 class Dr2, class V2, class TC2, class R2, class D2>
603 typename enable_if_interoperable<Dr1,Dr2,difference>::type
604 operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
605 iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
610 if `is_convertible<Dr2,Dr1>::value`
613 `difference` shall be
614 `iterator_traits<Dr1>::difference_type`.
617 `difference` shall be `iterator_traits<Dr2>::difference_type`
623 if `is_convertible<Dr2,Dr1>::value`
626 `-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)`.
629 `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)`.
635 [include facade_tutorial.qbk]