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