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