]> git.donarmstrong.com Git - rsem.git/blob - boost/iterator/iterator_facade.hpp
d84b402d592ee512f712cb1ec40e0a12647e3da9
[rsem.git] / 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/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