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