source: NonGTP/Boost/boost/iterator/iterator_facade.hpp @ 857

Revision 857, 29.3 KB checked in by igarcia, 18 years ago (diff)
Line 
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
39namespace 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 (constant) 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        const 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 const T*() const { return &m_value; }
306        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, <= 1200)
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, == 1200)
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                               
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
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,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, == 1200)
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, <= 1200)
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, == 1200)
725  template <class I, class V, class TC, class R, class D>
726  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
863BOOST_ITERATOR_FACADE_PLUS((
864  iterator_facade<Derived, V, TC, R, D> const& i
865  , typename Derived::difference_type n
866))
867
868BOOST_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
Note: See TracBrowser for help on using the repository browser.