Home | History | Annotate | Download | only in iterator
      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