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