annotate DEPENDENCIES/generic/include/boost/iterator/iterator_facade.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // (C) Copyright David Abrahams 2002.
Chris@16 2 // (C) Copyright Jeremy Siek 2002.
Chris@16 3 // (C) Copyright Thomas Witt 2002.
Chris@16 4 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 5 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 #ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP
Chris@16 8 #define BOOST_ITERATOR_FACADE_23022003THW_HPP
Chris@16 9
Chris@101 10 #include <boost/config.hpp>
Chris@16 11 #include <boost/iterator.hpp>
Chris@16 12 #include <boost/iterator/interoperable.hpp>
Chris@16 13 #include <boost/iterator/iterator_traits.hpp>
Chris@101 14 #include <boost/iterator/iterator_categories.hpp>
Chris@16 15
Chris@16 16 #include <boost/iterator/detail/facade_iterator_category.hpp>
Chris@16 17 #include <boost/iterator/detail/enable_if.hpp>
Chris@16 18
Chris@16 19 #include <boost/static_assert.hpp>
Chris@16 20 #include <boost/utility/addressof.hpp>
Chris@16 21
Chris@16 22 #include <boost/type_traits/is_same.hpp>
Chris@16 23 #include <boost/type_traits/add_const.hpp>
Chris@16 24 #include <boost/type_traits/add_pointer.hpp>
Chris@16 25 #include <boost/type_traits/remove_const.hpp>
Chris@16 26 #include <boost/type_traits/remove_reference.hpp>
Chris@16 27 #include <boost/type_traits/is_convertible.hpp>
Chris@16 28 #include <boost/type_traits/is_pod.hpp>
Chris@16 29
Chris@16 30 #include <boost/mpl/eval_if.hpp>
Chris@16 31 #include <boost/mpl/if.hpp>
Chris@16 32 #include <boost/mpl/or.hpp>
Chris@16 33 #include <boost/mpl/and.hpp>
Chris@16 34 #include <boost/mpl/not.hpp>
Chris@16 35 #include <boost/mpl/always.hpp>
Chris@16 36 #include <boost/mpl/apply.hpp>
Chris@16 37 #include <boost/mpl/identity.hpp>
Chris@16 38
Chris@16 39 #include <boost/iterator/detail/config_def.hpp> // this goes last
Chris@16 40
Chris@101 41 namespace boost {
Chris@101 42 namespace iterators {
Chris@101 43
Chris@16 44 // This forward declaration is required for the friend declaration
Chris@16 45 // in iterator_core_access
Chris@16 46 template <class I, class V, class TC, class R, class D> class iterator_facade;
Chris@16 47
Chris@16 48 namespace detail
Chris@16 49 {
Chris@16 50 // A binary metafunction class that always returns bool. VC6
Chris@16 51 // ICEs on mpl::always<bool>, probably because of the default
Chris@16 52 // parameters.
Chris@16 53 struct always_bool2
Chris@16 54 {
Chris@16 55 template <class T, class U>
Chris@16 56 struct apply
Chris@16 57 {
Chris@16 58 typedef bool type;
Chris@16 59 };
Chris@16 60 };
Chris@16 61
Chris@101 62 // The type trait checks if the category or traversal is at least as advanced as the specified required traversal
Chris@101 63 template< typename CategoryOrTraversal, typename Required >
Chris@101 64 struct is_traversal_at_least :
Chris@101 65 public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required >
Chris@101 66 {};
Chris@101 67
Chris@16 68 //
Chris@16 69 // enable if for use in operator implementation.
Chris@16 70 //
Chris@16 71 template <
Chris@16 72 class Facade1
Chris@16 73 , class Facade2
Chris@16 74 , class Return
Chris@16 75 >
Chris@101 76 struct enable_if_interoperable :
Chris@101 77 public boost::iterators::enable_if<
Chris@101 78 is_interoperable< Facade1, Facade2 >
Chris@101 79 , Return
Chris@101 80 >
Chris@101 81 {};
Chris@101 82
Chris@101 83 //
Chris@101 84 // enable if for use in implementation of operators specific for random access traversal.
Chris@101 85 //
Chris@101 86 template <
Chris@101 87 class Facade1
Chris@101 88 , class Facade2
Chris@101 89 , class Return
Chris@101 90 >
Chris@101 91 struct enable_if_interoperable_and_random_access_traversal :
Chris@101 92 public boost::iterators::enable_if<
Chris@101 93 mpl::and_<
Chris@101 94 is_interoperable< Facade1, Facade2 >
Chris@101 95 , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag >
Chris@101 96 , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag >
Chris@16 97 >
Chris@16 98 , Return
Chris@16 99 >
Chris@16 100 {};
Chris@16 101
Chris@16 102 //
Chris@16 103 // Generates associated types for an iterator_facade with the
Chris@16 104 // given parameters.
Chris@16 105 //
Chris@16 106 template <
Chris@16 107 class ValueParam
Chris@16 108 , class CategoryOrTraversal
Chris@101 109 , class Reference
Chris@16 110 , class Difference
Chris@16 111 >
Chris@16 112 struct iterator_facade_types
Chris@16 113 {
Chris@16 114 typedef typename facade_iterator_category<
Chris@16 115 CategoryOrTraversal, ValueParam, Reference
Chris@16 116 >::type iterator_category;
Chris@101 117
Chris@16 118 typedef typename remove_const<ValueParam>::type value_type;
Chris@101 119
Chris@16 120 // Not the real associated pointer type
Chris@16 121 typedef typename mpl::eval_if<
Chris@101 122 boost::iterators::detail::iterator_writability_disabled<ValueParam,Reference>
Chris@16 123 , add_pointer<const value_type>
Chris@16 124 , add_pointer<value_type>
Chris@16 125 >::type pointer;
Chris@101 126
Chris@16 127 # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
Chris@16 128 && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
Chris@16 129 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
Chris@16 130 || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
Chris@16 131 || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
Chris@16 132
Chris@16 133 // To interoperate with some broken library/compiler
Chris@16 134 // combinations, user-defined iterators must be derived from
Chris@16 135 // std::iterator. It is possible to implement a standard
Chris@16 136 // library for broken compilers without this limitation.
Chris@16 137 # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
Chris@16 138
Chris@16 139 typedef
Chris@16 140 iterator<iterator_category, value_type, Difference, pointer, Reference>
Chris@16 141 base;
Chris@16 142 # endif
Chris@16 143 };
Chris@16 144
Chris@16 145 // iterators whose dereference operators reference the same value
Chris@16 146 // for all iterators into the same sequence (like many input
Chris@16 147 // iterators) need help with their postfix ++: the referenced
Chris@16 148 // value must be read and stored away before the increment occurs
Chris@16 149 // so that *a++ yields the originally referenced element and not
Chris@16 150 // the next one.
Chris@16 151 template <class Iterator>
Chris@16 152 class postfix_increment_proxy
Chris@16 153 {
Chris@16 154 typedef typename iterator_value<Iterator>::type value_type;
Chris@16 155 public:
Chris@16 156 explicit postfix_increment_proxy(Iterator const& x)
Chris@16 157 : stored_value(*x)
Chris@16 158 {}
Chris@16 159
Chris@16 160 // Returning a mutable reference allows nonsense like
Chris@16 161 // (*r++).mutate(), but it imposes fewer assumptions about the
Chris@16 162 // behavior of the value_type. In particular, recall that
Chris@16 163 // (*r).mutate() is legal if operator* returns by value.
Chris@16 164 value_type&
Chris@16 165 operator*() const
Chris@16 166 {
Chris@16 167 return this->stored_value;
Chris@16 168 }
Chris@16 169 private:
Chris@16 170 mutable value_type stored_value;
Chris@16 171 };
Chris@101 172
Chris@16 173 //
Chris@16 174 // In general, we can't determine that such an iterator isn't
Chris@16 175 // writable -- we also need to store a copy of the old iterator so
Chris@16 176 // that it can be written into.
Chris@16 177 template <class Iterator>
Chris@16 178 class writable_postfix_increment_proxy
Chris@16 179 {
Chris@16 180 typedef typename iterator_value<Iterator>::type value_type;
Chris@16 181 public:
Chris@16 182 explicit writable_postfix_increment_proxy(Iterator const& x)
Chris@16 183 : stored_value(*x)
Chris@16 184 , stored_iterator(x)
Chris@16 185 {}
Chris@16 186
Chris@16 187 // Dereferencing must return a proxy so that both *r++ = o and
Chris@16 188 // value_type(*r++) can work. In this case, *r is the same as
Chris@16 189 // *r++, and the conversion operator below is used to ensure
Chris@16 190 // readability.
Chris@16 191 writable_postfix_increment_proxy const&
Chris@16 192 operator*() const
Chris@16 193 {
Chris@16 194 return *this;
Chris@16 195 }
Chris@16 196
Chris@16 197 // Provides readability of *r++
Chris@16 198 operator value_type&() const
Chris@16 199 {
Chris@16 200 return stored_value;
Chris@16 201 }
Chris@16 202
Chris@16 203 // Provides writability of *r++
Chris@16 204 template <class T>
Chris@16 205 T const& operator=(T const& x) const
Chris@16 206 {
Chris@16 207 *this->stored_iterator = x;
Chris@16 208 return x;
Chris@16 209 }
Chris@16 210
Chris@16 211 // This overload just in case only non-const objects are writable
Chris@16 212 template <class T>
Chris@16 213 T& operator=(T& x) const
Chris@16 214 {
Chris@16 215 *this->stored_iterator = x;
Chris@16 216 return x;
Chris@16 217 }
Chris@16 218
Chris@16 219 // Provides X(r++)
Chris@16 220 operator Iterator const&() const
Chris@16 221 {
Chris@16 222 return stored_iterator;
Chris@16 223 }
Chris@101 224
Chris@16 225 private:
Chris@16 226 mutable value_type stored_value;
Chris@16 227 Iterator stored_iterator;
Chris@16 228 };
Chris@16 229
Chris@16 230 # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Chris@16 231
Chris@16 232 template <class Reference, class Value>
Chris@16 233 struct is_non_proxy_reference_impl
Chris@16 234 {
Chris@16 235 static Reference r;
Chris@101 236
Chris@16 237 template <class R>
Chris@16 238 static typename mpl::if_<
Chris@16 239 is_convertible<
Chris@16 240 R const volatile*
Chris@16 241 , Value const volatile*
Chris@16 242 >
Chris@16 243 , char[1]
Chris@16 244 , char[2]
Chris@16 245 >::type& helper(R const&);
Chris@101 246
Chris@16 247 BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);
Chris@16 248 };
Chris@101 249
Chris@16 250 template <class Reference, class Value>
Chris@16 251 struct is_non_proxy_reference
Chris@16 252 : mpl::bool_<
Chris@16 253 is_non_proxy_reference_impl<Reference, Value>::value
Chris@16 254 >
Chris@16 255 {};
Chris@101 256 # else
Chris@16 257 template <class Reference, class Value>
Chris@16 258 struct is_non_proxy_reference
Chris@16 259 : is_convertible<
Chris@16 260 typename remove_reference<Reference>::type
Chris@16 261 const volatile*
Chris@16 262 , Value const volatile*
Chris@16 263 >
Chris@16 264 {};
Chris@101 265 # endif
Chris@101 266
Chris@16 267 // A metafunction to choose the result type of postfix ++
Chris@16 268 //
Chris@16 269 // Because the C++98 input iterator requirements say that *r++ has
Chris@16 270 // type T (value_type), implementations of some standard
Chris@16 271 // algorithms like lexicographical_compare may use constructions
Chris@16 272 // like:
Chris@16 273 //
Chris@16 274 // *r++ < *s++
Chris@16 275 //
Chris@16 276 // If *r++ returns a proxy (as required if r is writable but not
Chris@16 277 // multipass), this sort of expression will fail unless the proxy
Chris@16 278 // supports the operator<. Since there are any number of such
Chris@16 279 // operations, we're not going to try to support them. Therefore,
Chris@16 280 // even if r++ returns a proxy, *r++ will only return a proxy if
Chris@16 281 // *r also returns a proxy.
Chris@16 282 template <class Iterator, class Value, class Reference, class CategoryOrTraversal>
Chris@16 283 struct postfix_increment_result
Chris@16 284 : mpl::eval_if<
Chris@16 285 mpl::and_<
Chris@16 286 // A proxy is only needed for readable iterators
Chris@16 287 is_convertible<Reference,Value const&>
Chris@101 288
Chris@16 289 // No multipass iterator can have values that disappear
Chris@16 290 // before positions can be re-visited
Chris@16 291 , mpl::not_<
Chris@16 292 is_convertible<
Chris@16 293 typename iterator_category_to_traversal<CategoryOrTraversal>::type
Chris@16 294 , forward_traversal_tag
Chris@16 295 >
Chris@16 296 >
Chris@16 297 >
Chris@16 298 , mpl::if_<
Chris@16 299 is_non_proxy_reference<Reference,Value>
Chris@16 300 , postfix_increment_proxy<Iterator>
Chris@16 301 , writable_postfix_increment_proxy<Iterator>
Chris@16 302 >
Chris@16 303 , mpl::identity<Iterator>
Chris@16 304 >
Chris@16 305 {};
Chris@16 306
Chris@16 307 // operator->() needs special support for input iterators to strictly meet the
Chris@16 308 // standard's requirements. If *i is not a reference type, we must still
Chris@16 309 // produce an lvalue to which a pointer can be formed. We do that by
Chris@16 310 // returning a proxy object containing an instance of the reference object.
Chris@16 311 template <class Reference, class Pointer>
Chris@16 312 struct operator_arrow_dispatch // proxy references
Chris@16 313 {
Chris@16 314 struct proxy
Chris@16 315 {
Chris@16 316 explicit proxy(Reference const & x) : m_ref(x) {}
Chris@16 317 Reference* operator->() { return boost::addressof(m_ref); }
Chris@16 318 // This function is needed for MWCW and BCC, which won't call
Chris@16 319 // operator-> again automatically per 13.3.1.2 para 8
Chris@16 320 operator Reference*() { return boost::addressof(m_ref); }
Chris@16 321 Reference m_ref;
Chris@16 322 };
Chris@16 323 typedef proxy result_type;
Chris@16 324 static result_type apply(Reference const & x)
Chris@16 325 {
Chris@16 326 return result_type(x);
Chris@16 327 }
Chris@16 328 };
Chris@16 329
Chris@16 330 template <class T, class Pointer>
Chris@16 331 struct operator_arrow_dispatch<T&, Pointer> // "real" references
Chris@16 332 {
Chris@16 333 typedef Pointer result_type;
Chris@16 334 static result_type apply(T& x)
Chris@16 335 {
Chris@16 336 return boost::addressof(x);
Chris@16 337 }
Chris@16 338 };
Chris@16 339
Chris@16 340 // A proxy return type for operator[], needed to deal with
Chris@16 341 // iterators that may invalidate referents upon destruction.
Chris@16 342 // Consider the temporary iterator in *(a + n)
Chris@16 343 template <class Iterator>
Chris@16 344 class operator_brackets_proxy
Chris@16 345 {
Chris@16 346 // Iterator is actually an iterator_facade, so we do not have to
Chris@16 347 // go through iterator_traits to access the traits.
Chris@16 348 typedef typename Iterator::reference reference;
Chris@16 349 typedef typename Iterator::value_type value_type;
Chris@16 350
Chris@16 351 public:
Chris@16 352 operator_brackets_proxy(Iterator const& iter)
Chris@16 353 : m_iter(iter)
Chris@16 354 {}
Chris@16 355
Chris@16 356 operator reference() const
Chris@16 357 {
Chris@16 358 return *m_iter;
Chris@16 359 }
Chris@16 360
Chris@16 361 operator_brackets_proxy& operator=(value_type const& val)
Chris@16 362 {
Chris@16 363 *m_iter = val;
Chris@16 364 return *this;
Chris@16 365 }
Chris@16 366
Chris@16 367 private:
Chris@16 368 Iterator m_iter;
Chris@16 369 };
Chris@16 370
Chris@16 371 // A metafunction that determines whether operator[] must return a
Chris@16 372 // proxy, or whether it can simply return a copy of the value_type.
Chris@16 373 template <class ValueType, class Reference>
Chris@16 374 struct use_operator_brackets_proxy
Chris@16 375 : mpl::not_<
Chris@16 376 mpl::and_<
Chris@16 377 // Really we want an is_copy_constructible trait here,
Chris@16 378 // but is_POD will have to suffice in the meantime.
Chris@16 379 boost::is_POD<ValueType>
Chris@16 380 , iterator_writability_disabled<ValueType,Reference>
Chris@16 381 >
Chris@16 382 >
Chris@16 383 {};
Chris@101 384
Chris@16 385 template <class Iterator, class Value, class Reference>
Chris@16 386 struct operator_brackets_result
Chris@16 387 {
Chris@16 388 typedef typename mpl::if_<
Chris@16 389 use_operator_brackets_proxy<Value,Reference>
Chris@16 390 , operator_brackets_proxy<Iterator>
Chris@16 391 , Value
Chris@16 392 >::type type;
Chris@16 393 };
Chris@16 394
Chris@16 395 template <class Iterator>
Chris@16 396 operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
Chris@16 397 {
Chris@16 398 return operator_brackets_proxy<Iterator>(iter);
Chris@16 399 }
Chris@16 400
Chris@16 401 template <class Iterator>
Chris@16 402 typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
Chris@16 403 {
Chris@16 404 return *iter;
Chris@16 405 }
Chris@16 406
Chris@16 407 struct choose_difference_type
Chris@16 408 {
Chris@16 409 template <class I1, class I2>
Chris@16 410 struct apply
Chris@16 411 :
Chris@16 412 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
Chris@16 413 iterator_difference<I1>
Chris@101 414 # else
Chris@16 415 mpl::eval_if<
Chris@16 416 is_convertible<I2,I1>
Chris@16 417 , iterator_difference<I1>
Chris@16 418 , iterator_difference<I2>
Chris@16 419 >
Chris@101 420 # endif
Chris@16 421 {};
Chris@16 422
Chris@16 423 };
Chris@101 424
Chris@101 425 template <
Chris@101 426 class Derived
Chris@101 427 , class Value
Chris@101 428 , class CategoryOrTraversal
Chris@101 429 , class Reference
Chris@101 430 , class Difference
Chris@101 431 , bool IsBidirectionalTraversal
Chris@101 432 , bool IsRandomAccessTraversal
Chris@101 433 >
Chris@101 434 class iterator_facade_base;
Chris@101 435
Chris@16 436 } // namespace detail
Chris@16 437
Chris@16 438
Chris@16 439 // Macros which describe the declarations of binary operators
Chris@16 440 # ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
Chris@101 441 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
Chris@16 442 template < \
Chris@16 443 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
Chris@16 444 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
Chris@16 445 > \
Chris@16 446 prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
Chris@16 447 operator op( \
Chris@16 448 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
Chris@16 449 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
Chris@101 450 # else
Chris@101 451 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
Chris@16 452 template < \
Chris@16 453 class Derived1, class V1, class TC1, class Reference1, class Difference1 \
Chris@16 454 , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
Chris@16 455 > \
Chris@101 456 prefix typename enabler< \
Chris@16 457 Derived1, Derived2 \
Chris@16 458 , typename mpl::apply2<result_type,Derived1,Derived2>::type \
Chris@16 459 >::type \
Chris@16 460 operator op( \
Chris@16 461 iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
Chris@16 462 , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
Chris@101 463 # endif
Chris@101 464
Chris@101 465 # define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
Chris@101 466 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable)
Chris@101 467
Chris@101 468 # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \
Chris@101 469 BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal)
Chris@16 470
Chris@16 471 # define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
Chris@16 472 template <class Derived, class V, class TC, class R, class D> \
Chris@101 473 prefix typename boost::iterators::enable_if< \
Chris@101 474 boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \
Chris@101 475 Derived \
Chris@101 476 >::type operator+ args
Chris@16 477
Chris@16 478 //
Chris@16 479 // Helper class for granting access to the iterator core interface.
Chris@16 480 //
Chris@16 481 // The simple core interface is used by iterator_facade. The core
Chris@16 482 // interface of a user/library defined iterator type should not be made public
Chris@16 483 // so that it does not clutter the public interface. Instead iterator_core_access
Chris@16 484 // should be made friend so that iterator_facade can access the core
Chris@16 485 // interface through iterator_core_access.
Chris@16 486 //
Chris@16 487 class iterator_core_access
Chris@16 488 {
Chris@101 489 # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
Chris@16 490 // Tasteless as this may seem, making all members public allows member templates
Chris@16 491 // to work in the absence of member template friends.
Chris@16 492 public:
Chris@16 493 # else
Chris@101 494
Chris@16 495 template <class I, class V, class TC, class R, class D> friend class iterator_facade;
Chris@101 496 template <class I, class V, class TC, class R, class D, bool IsBidirectionalTraversal, bool IsRandomAccessTraversal>
Chris@101 497 friend class detail::iterator_facade_base;
Chris@16 498
Chris@16 499 # define BOOST_ITERATOR_FACADE_RELATION(op) \
Chris@101 500 BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2);
Chris@16 501
Chris@16 502 BOOST_ITERATOR_FACADE_RELATION(==)
Chris@16 503 BOOST_ITERATOR_FACADE_RELATION(!=)
Chris@16 504
Chris@16 505 # undef BOOST_ITERATOR_FACADE_RELATION
Chris@16 506
Chris@101 507 # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \
Chris@101 508 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2);
Chris@101 509
Chris@101 510 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<)
Chris@101 511 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>)
Chris@101 512 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=)
Chris@101 513 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=)
Chris@101 514
Chris@101 515 # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
Chris@101 516
Chris@101 517 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(
Chris@101 518 friend, -, boost::iterators::detail::choose_difference_type)
Chris@16 519 ;
Chris@16 520
Chris@16 521 BOOST_ITERATOR_FACADE_PLUS_HEAD(
Chris@16 522 friend inline
Chris@101 523 , (iterator_facade<Derived, V, TC, R, D> const&
Chris@101 524 , typename Derived::difference_type)
Chris@16 525 )
Chris@16 526 ;
Chris@16 527
Chris@16 528 BOOST_ITERATOR_FACADE_PLUS_HEAD(
Chris@16 529 friend inline
Chris@16 530 , (typename Derived::difference_type
Chris@101 531 , iterator_facade<Derived, V, TC, R, D> const&)
Chris@16 532 )
Chris@16 533 ;
Chris@16 534
Chris@16 535 # endif
Chris@16 536
Chris@16 537 template <class Facade>
Chris@16 538 static typename Facade::reference dereference(Facade const& f)
Chris@16 539 {
Chris@16 540 return f.dereference();
Chris@16 541 }
Chris@16 542
Chris@16 543 template <class Facade>
Chris@16 544 static void increment(Facade& f)
Chris@16 545 {
Chris@16 546 f.increment();
Chris@16 547 }
Chris@16 548
Chris@16 549 template <class Facade>
Chris@16 550 static void decrement(Facade& f)
Chris@16 551 {
Chris@16 552 f.decrement();
Chris@16 553 }
Chris@16 554
Chris@16 555 template <class Facade1, class Facade2>
Chris@16 556 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
Chris@16 557 {
Chris@16 558 return f1.equal(f2);
Chris@16 559 }
Chris@16 560
Chris@16 561 template <class Facade1, class Facade2>
Chris@16 562 static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
Chris@16 563 {
Chris@16 564 return f2.equal(f1);
Chris@16 565 }
Chris@16 566
Chris@16 567 template <class Facade>
Chris@16 568 static void advance(Facade& f, typename Facade::difference_type n)
Chris@16 569 {
Chris@16 570 f.advance(n);
Chris@16 571 }
Chris@16 572
Chris@16 573 template <class Facade1, class Facade2>
Chris@16 574 static typename Facade1::difference_type distance_from(
Chris@16 575 Facade1 const& f1, Facade2 const& f2, mpl::true_)
Chris@16 576 {
Chris@16 577 return -f1.distance_to(f2);
Chris@16 578 }
Chris@16 579
Chris@16 580 template <class Facade1, class Facade2>
Chris@16 581 static typename Facade2::difference_type distance_from(
Chris@16 582 Facade1 const& f1, Facade2 const& f2, mpl::false_)
Chris@16 583 {
Chris@16 584 return f2.distance_to(f1);
Chris@16 585 }
Chris@16 586
Chris@16 587 //
Chris@16 588 // Curiously Recurring Template interface.
Chris@16 589 //
Chris@16 590 template <class I, class V, class TC, class R, class D>
Chris@16 591 static I& derived(iterator_facade<I,V,TC,R,D>& facade)
Chris@16 592 {
Chris@16 593 return *static_cast<I*>(&facade);
Chris@16 594 }
Chris@16 595
Chris@16 596 template <class I, class V, class TC, class R, class D>
Chris@16 597 static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
Chris@16 598 {
Chris@16 599 return *static_cast<I const*>(&facade);
Chris@16 600 }
Chris@16 601
Chris@16 602 // objects of this class are useless
Chris@101 603 BOOST_DELETED_FUNCTION(iterator_core_access())
Chris@16 604 };
Chris@16 605
Chris@101 606 namespace detail {
Chris@101 607
Chris@101 608 // Implementation for forward traversal iterators
Chris@101 609 template <
Chris@101 610 class Derived
Chris@101 611 , class Value
Chris@101 612 , class CategoryOrTraversal
Chris@101 613 , class Reference
Chris@101 614 , class Difference
Chris@101 615 >
Chris@101 616 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
Chris@101 617 # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
Chris@101 618 : public boost::iterators::detail::iterator_facade_types<
Chris@101 619 Value, CategoryOrTraversal, Reference, Difference
Chris@101 620 >::base
Chris@101 621 # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
Chris@101 622 # endif
Chris@101 623 {
Chris@101 624 private:
Chris@101 625 typedef boost::iterators::detail::iterator_facade_types<
Chris@101 626 Value, CategoryOrTraversal, Reference, Difference
Chris@101 627 > associated_types;
Chris@101 628
Chris@101 629 typedef boost::iterators::detail::operator_arrow_dispatch<
Chris@101 630 Reference
Chris@101 631 , typename associated_types::pointer
Chris@101 632 > operator_arrow_dispatch_;
Chris@101 633
Chris@101 634 public:
Chris@101 635 typedef typename associated_types::value_type value_type;
Chris@101 636 typedef Reference reference;
Chris@101 637 typedef Difference difference_type;
Chris@101 638
Chris@101 639 typedef typename operator_arrow_dispatch_::result_type pointer;
Chris@101 640
Chris@101 641 typedef typename associated_types::iterator_category iterator_category;
Chris@101 642
Chris@101 643 public:
Chris@101 644 reference operator*() const
Chris@101 645 {
Chris@101 646 return iterator_core_access::dereference(this->derived());
Chris@101 647 }
Chris@101 648
Chris@101 649 pointer operator->() const
Chris@101 650 {
Chris@101 651 return operator_arrow_dispatch_::apply(*this->derived());
Chris@101 652 }
Chris@101 653
Chris@101 654 Derived& operator++()
Chris@101 655 {
Chris@101 656 iterator_core_access::increment(this->derived());
Chris@101 657 return this->derived();
Chris@101 658 }
Chris@101 659
Chris@101 660 protected:
Chris@101 661 //
Chris@101 662 // Curiously Recurring Template interface.
Chris@101 663 //
Chris@101 664 Derived& derived()
Chris@101 665 {
Chris@101 666 return *static_cast<Derived*>(this);
Chris@101 667 }
Chris@101 668
Chris@101 669 Derived const& derived() const
Chris@101 670 {
Chris@101 671 return *static_cast<Derived const*>(this);
Chris@101 672 }
Chris@101 673 };
Chris@101 674
Chris@101 675 // Implementation for bidirectional traversal iterators
Chris@101 676 template <
Chris@101 677 class Derived
Chris@101 678 , class Value
Chris@101 679 , class CategoryOrTraversal
Chris@101 680 , class Reference
Chris@101 681 , class Difference
Chris@101 682 >
Chris@101 683 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > :
Chris@101 684 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
Chris@101 685 {
Chris@101 686 public:
Chris@101 687 Derived& operator--()
Chris@101 688 {
Chris@101 689 iterator_core_access::decrement(this->derived());
Chris@101 690 return this->derived();
Chris@101 691 }
Chris@101 692
Chris@101 693 Derived operator--(int)
Chris@101 694 {
Chris@101 695 Derived tmp(this->derived());
Chris@101 696 --*this;
Chris@101 697 return tmp;
Chris@101 698 }
Chris@101 699 };
Chris@101 700
Chris@101 701 // Implementation for random access traversal iterators
Chris@101 702 template <
Chris@101 703 class Derived
Chris@101 704 , class Value
Chris@101 705 , class CategoryOrTraversal
Chris@101 706 , class Reference
Chris@101 707 , class Difference
Chris@101 708 >
Chris@101 709 class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > :
Chris@101 710 public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false >
Chris@101 711 {
Chris@101 712 private:
Chris@101 713 typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type;
Chris@101 714
Chris@101 715 public:
Chris@101 716 typedef typename base_type::reference reference;
Chris@101 717 typedef typename base_type::difference_type difference_type;
Chris@101 718
Chris@101 719 public:
Chris@101 720 typename boost::iterators::detail::operator_brackets_result<Derived, Value, reference>::type
Chris@101 721 operator[](difference_type n) const
Chris@101 722 {
Chris@101 723 typedef boost::iterators::detail::use_operator_brackets_proxy<Value, Reference> use_proxy;
Chris@101 724
Chris@101 725 return boost::iterators::detail::make_operator_brackets_result<Derived>(
Chris@101 726 this->derived() + n
Chris@101 727 , use_proxy()
Chris@101 728 );
Chris@101 729 }
Chris@101 730
Chris@101 731 Derived& operator+=(difference_type n)
Chris@101 732 {
Chris@101 733 iterator_core_access::advance(this->derived(), n);
Chris@101 734 return this->derived();
Chris@101 735 }
Chris@101 736
Chris@101 737 Derived& operator-=(difference_type n)
Chris@101 738 {
Chris@101 739 iterator_core_access::advance(this->derived(), -n);
Chris@101 740 return this->derived();
Chris@101 741 }
Chris@101 742
Chris@101 743 Derived operator-(difference_type x) const
Chris@101 744 {
Chris@101 745 Derived result(this->derived());
Chris@101 746 return result -= x;
Chris@101 747 }
Chris@101 748 };
Chris@101 749
Chris@101 750 } // namespace detail
Chris@101 751
Chris@16 752 //
Chris@16 753 // iterator_facade - use as a public base class for defining new
Chris@16 754 // standard-conforming iterators.
Chris@16 755 //
Chris@16 756 template <
Chris@16 757 class Derived // The derived iterator type being constructed
Chris@16 758 , class Value
Chris@16 759 , class CategoryOrTraversal
Chris@16 760 , class Reference = Value&
Chris@16 761 , class Difference = std::ptrdiff_t
Chris@16 762 >
Chris@101 763 class iterator_facade :
Chris@101 764 public detail::iterator_facade_base<
Chris@101 765 Derived,
Chris@101 766 Value,
Chris@101 767 CategoryOrTraversal,
Chris@101 768 Reference,
Chris@101 769 Difference,
Chris@101 770 detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value,
Chris@101 771 detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value
Chris@101 772 >
Chris@16 773 {
Chris@101 774 protected:
Chris@16 775 // For use by derived classes
Chris@16 776 typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
Chris@16 777 };
Chris@16 778
Chris@16 779 template <class I, class V, class TC, class R, class D>
Chris@101 780 inline typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
Chris@16 781 operator++(
Chris@16 782 iterator_facade<I,V,TC,R,D>& i
Chris@16 783 , int
Chris@16 784 )
Chris@16 785 {
Chris@101 786 typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
Chris@16 787 tmp(*static_cast<I*>(&i));
Chris@101 788
Chris@16 789 ++i;
Chris@101 790
Chris@16 791 return tmp;
Chris@16 792 }
Chris@16 793
Chris@101 794
Chris@16 795 //
Chris@16 796 // Comparison operator implementation. The library supplied operators
Chris@16 797 // enables the user to provide fully interoperable constant/mutable
Chris@16 798 // iterator types. I.e. the library provides all operators
Chris@16 799 // for all mutable/constant iterator combinations.
Chris@16 800 //
Chris@16 801 // Note though that this kind of interoperability for constant/mutable
Chris@16 802 // iterators is not required by the standard for container iterators.
Chris@16 803 // All the standard asks for is a conversion mutable -> constant.
Chris@16 804 // Most standard library implementations nowadays provide fully interoperable
Chris@16 805 // iterator implementations, but there are still heavily used implementations
Chris@16 806 // that do not provide them. (Actually it's even worse, they do not provide
Chris@16 807 // them for only a few iterators.)
Chris@16 808 //
Chris@16 809 // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
Chris@16 810 // enable the user to turn off mixed type operators
Chris@16 811 //
Chris@16 812 // The library takes care to provide only the right operator overloads.
Chris@16 813 // I.e.
Chris@16 814 //
Chris@16 815 // bool operator==(Iterator, Iterator);
Chris@16 816 // bool operator==(ConstIterator, Iterator);
Chris@16 817 // bool operator==(Iterator, ConstIterator);
Chris@16 818 // bool operator==(ConstIterator, ConstIterator);
Chris@16 819 //
Chris@16 820 // ...
Chris@16 821 //
Chris@16 822 // In order to do so it uses c++ idioms that are not yet widely supported
Chris@16 823 // by current compiler releases. The library is designed to degrade gracefully
Chris@16 824 // in the face of compiler deficiencies. In general compiler
Chris@16 825 // deficiencies result in less strict error checking and more obscure
Chris@16 826 // error messages, functionality is not affected.
Chris@16 827 //
Chris@16 828 // For full operation compiler support for "Substitution Failure Is Not An Error"
Chris@16 829 // (aka. enable_if) and boost::is_convertible is required.
Chris@16 830 //
Chris@16 831 // The following problems occur if support is lacking.
Chris@16 832 //
Chris@16 833 // Pseudo code
Chris@16 834 //
Chris@16 835 // ---------------
Chris@16 836 // AdaptorA<Iterator1> a1;
Chris@16 837 // AdaptorA<Iterator2> a2;
Chris@16 838 //
Chris@16 839 // // This will result in a no such overload error in full operation
Chris@16 840 // // If enable_if or is_convertible is not supported
Chris@16 841 // // The instantiation will fail with an error hopefully indicating that
Chris@16 842 // // there is no operator== for Iterator1, Iterator2
Chris@16 843 // // The same will happen if no enable_if is used to remove
Chris@16 844 // // false overloads from the templated conversion constructor
Chris@16 845 // // of AdaptorA.
Chris@16 846 //
Chris@16 847 // a1 == a2;
Chris@16 848 // ----------------
Chris@16 849 //
Chris@16 850 // AdaptorA<Iterator> a;
Chris@16 851 // AdaptorB<Iterator> b;
Chris@16 852 //
Chris@16 853 // // This will result in a no such overload error in full operation
Chris@16 854 // // If enable_if is not supported the static assert used
Chris@16 855 // // in the operator implementation will fail.
Chris@16 856 // // This will accidently work if is_convertible is not supported.
Chris@16 857 //
Chris@16 858 // a == b;
Chris@16 859 // ----------------
Chris@16 860 //
Chris@16 861
Chris@16 862 # ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
Chris@16 863 # define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
Chris@16 864 # else
Chris@16 865 # define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
Chris@16 866 # endif
Chris@16 867
Chris@16 868 # define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
Chris@16 869 BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
Chris@16 870 { \
Chris@16 871 /* For those compilers that do not support enable_if */ \
Chris@16 872 BOOST_STATIC_ASSERT(( \
Chris@16 873 is_interoperable< Derived1, Derived2 >::value \
Chris@16 874 )); \
Chris@16 875 return_prefix iterator_core_access::base_op( \
Chris@16 876 *static_cast<Derived1 const*>(&lhs) \
Chris@16 877 , *static_cast<Derived2 const*>(&rhs) \
Chris@16 878 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
Chris@16 879 ); \
Chris@16 880 }
Chris@16 881
Chris@16 882 # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
Chris@16 883 BOOST_ITERATOR_FACADE_INTEROP( \
Chris@16 884 op \
Chris@101 885 , boost::iterators::detail::always_bool2 \
Chris@16 886 , return_prefix \
Chris@16 887 , base_op \
Chris@16 888 )
Chris@16 889
Chris@16 890 BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
Chris@16 891 BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
Chris@16 892
Chris@16 893 # undef BOOST_ITERATOR_FACADE_RELATION
Chris@16 894
Chris@101 895
Chris@101 896 # define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \
Chris@101 897 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \
Chris@101 898 { \
Chris@101 899 /* For those compilers that do not support enable_if */ \
Chris@101 900 BOOST_STATIC_ASSERT(( \
Chris@101 901 is_interoperable< Derived1, Derived2 >::value && \
Chris@101 902 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \
Chris@101 903 boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \
Chris@101 904 )); \
Chris@101 905 return_prefix iterator_core_access::base_op( \
Chris@101 906 *static_cast<Derived1 const*>(&lhs) \
Chris@101 907 , *static_cast<Derived2 const*>(&rhs) \
Chris@101 908 , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
Chris@101 909 ); \
Chris@101 910 }
Chris@101 911
Chris@101 912 # define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \
Chris@101 913 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \
Chris@101 914 op \
Chris@101 915 , boost::iterators::detail::always_bool2 \
Chris@101 916 , return_prefix \
Chris@101 917 , base_op \
Chris@101 918 )
Chris@101 919
Chris@101 920 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from)
Chris@101 921 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from)
Chris@101 922 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from)
Chris@101 923 BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from)
Chris@101 924
Chris@101 925 # undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
Chris@101 926
Chris@16 927 // operator- requires an additional part in the static assertion
Chris@101 928 BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(
Chris@16 929 -
Chris@101 930 , boost::iterators::detail::choose_difference_type
Chris@16 931 , return
Chris@16 932 , distance_from
Chris@16 933 )
Chris@101 934
Chris@16 935 # undef BOOST_ITERATOR_FACADE_INTEROP
Chris@101 936 # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS
Chris@16 937
Chris@16 938 # define BOOST_ITERATOR_FACADE_PLUS(args) \
Chris@16 939 BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
Chris@16 940 { \
Chris@16 941 Derived tmp(static_cast<Derived const&>(i)); \
Chris@16 942 return tmp += n; \
Chris@16 943 }
Chris@16 944
Chris@101 945 BOOST_ITERATOR_FACADE_PLUS((
Chris@101 946 iterator_facade<Derived, V, TC, R, D> const& i
Chris@101 947 , typename Derived::difference_type n
Chris@101 948 ))
Chris@16 949
Chris@101 950 BOOST_ITERATOR_FACADE_PLUS((
Chris@101 951 typename Derived::difference_type n
Chris@16 952 , iterator_facade<Derived, V, TC, R, D> const& i
Chris@101 953 ))
Chris@101 954
Chris@16 955 # undef BOOST_ITERATOR_FACADE_PLUS
Chris@16 956 # undef BOOST_ITERATOR_FACADE_PLUS_HEAD
Chris@16 957
Chris@101 958 # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
Chris@101 959 # undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD
Chris@101 960 # undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL
Chris@101 961
Chris@101 962 } // namespace iterators
Chris@101 963
Chris@101 964 using iterators::iterator_core_access;
Chris@101 965 using iterators::iterator_facade;
Chris@101 966
Chris@16 967 } // namespace boost
Chris@16 968
Chris@16 969 #include <boost/iterator/detail/config_undef.hpp>
Chris@16 970
Chris@16 971 #endif // BOOST_ITERATOR_FACADE_23022003THW_HPP