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