Brian Silverman | 5962333 | 2018-08-04 23:36:56 -0700 | [diff] [blame^] | 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 | |
| 105 | The ``iterator_category`` member of ``iterator_facade`` is |
| 106 | |
| 107 | .. parsed-literal:: |
| 108 | |
| 109 | *iterator-category*\ (CategoryOrTraversal, reference, value_type) |
| 110 | |
| 111 | where *iterator-category* is defined as follows: |
| 112 | |
| 113 | .. include:: facade_iterator_category.rst |
| 114 | |
| 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`` |
| 122 | were 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 | |
| 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. |
| 148 | |
| 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``. |
| 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 | |
| 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``. |
| 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)``. |