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

Revision 857, 11.4 KB checked in by igarcia, 19 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_ADAPTOR_23022003THW_HPP
8#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
9
10#include <boost/static_assert.hpp>
11#include <boost/iterator.hpp>
12#include <boost/detail/iterator.hpp>
13
14#include <boost/iterator/iterator_categories.hpp>
15#include <boost/iterator/iterator_facade.hpp>
16#include <boost/iterator/detail/enable_if.hpp>
17
18#include <boost/mpl/and.hpp>
19#include <boost/mpl/not.hpp>
20#include <boost/mpl/or.hpp>
21
22#include <boost/type_traits/is_same.hpp>
23#include <boost/type_traits/is_convertible.hpp>
24
25#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
26# include <boost/type_traits/remove_reference.hpp>
27#else
28# include <boost/type_traits/add_reference.hpp>
29#endif
30
31#include <boost/iterator/detail/config_def.hpp>
32
33#include <boost/iterator/iterator_traits.hpp>
34
35namespace boost
36{
37  // Used as a default template argument internally, merely to
38  // indicate "use the default", this can also be passed by users
39  // explicitly in order to specify that the default should be used.
40  struct use_default;
41 
42# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
43  // the incompleteness of use_default causes massive problems for
44  // is_convertible (naturally).  This workaround is fortunately not
45  // needed for vc6/vc7.
46  template<class To>
47  struct is_convertible<use_default,To>
48    : mpl::false_ {};
49# endif
50 
51  namespace detail
52  {
53
54    //
55    // Result type used in enable_if_convertible meta function.
56    // This can be an incomplete type, as only pointers to
57    // enable_if_convertible< ... >::type are used.
58    // We could have used void for this, but conversion to
59    // void* is just to easy.
60    //
61    struct enable_type;
62  }
63
64
65  //
66  // enable_if for use in adapted iterators constructors.
67  //
68  // In order to provide interoperability between adapted constant and
69  // mutable iterators, adapted iterators will usually provide templated
70  // conversion constructors of the following form
71  //
72  // template <class BaseIterator>
73  // class adapted_iterator :
74  //   public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
75  // {
76  // public:
77  //   
78  //   ...
79  //
80  //   template <class OtherIterator>
81  //   adapted_iterator(
82  //       OtherIterator const& it
83  //     , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
84  //
85  //   ...
86  // };
87  //
88  // enable_if_convertible is used to remove those overloads from the overload
89  // set that cannot be instantiated. For all practical purposes only overloads
90  // for constant/mutable interaction will remain. This has the advantage that
91  // meta functions like boost::is_convertible do not return false positives,
92  // as they can only look at the signature of the conversion constructor
93  // and not at the actual instantiation.
94  //
95  // enable_if_interoperable can be safely used in user code. It falls back to
96  // always enabled for compilers that don't support enable_if or is_convertible.
97  // There is no need for compiler specific workarounds in user code.
98  //
99  // The operators implementation relies on boost::is_convertible not returning
100  // false positives for user/library defined iterator types. See comments
101  // on operator implementation for consequences.
102  //
103#  if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
104 
105  template<typename From, typename To>
106  struct enable_if_convertible
107  {
108     typedef typename mpl::if_<
109         mpl::or_<
110             is_same<From,To>
111           , is_convertible<From, To>
112         >
113      , detail::enable_type
114      , int&
115     >::type type;
116  };
117 
118#  elif defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
119 
120  template <class From, class To>
121  struct enable_if_convertible
122  {
123      typedef detail::enable_type type;
124  };
125 
126#  elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300
127 
128  // For some reason vc7.1 needs us to "cut off" instantiation
129  // of is_convertible in a few cases.
130  template<typename From, typename To>
131  struct enable_if_convertible
132    : iterators::enable_if<
133        mpl::or_<
134            is_same<From,To>
135          , is_convertible<From, To>
136        >
137      , detail::enable_type
138    >
139  {};
140 
141#  else
142 
143  template<typename From, typename To>
144  struct enable_if_convertible
145    : iterators::enable_if<
146          is_convertible<From, To>
147        , detail::enable_type
148      >
149  {};
150     
151# endif
152 
153  //
154  // Default template argument handling for iterator_adaptor
155  //
156  namespace detail
157  {
158    // If T is use_default, return the result of invoking
159    // DefaultNullaryFn, otherwise return T.
160    template <class T, class DefaultNullaryFn>
161    struct ia_dflt_help
162      : mpl::eval_if<
163            is_same<T, use_default>
164          , DefaultNullaryFn
165          , mpl::identity<T>
166        >
167    {
168    };
169
170    // A metafunction which computes an iterator_adaptor's base class,
171    // a specialization of iterator_facade.
172    template <
173        class Derived
174      , class Base
175      , class Value
176      , class Traversal
177      , class Reference
178      , class Difference
179    >
180    struct iterator_adaptor_base
181    {
182        typedef iterator_facade<
183            Derived
184           
185# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
186          , typename detail::ia_dflt_help<
187                Value
188              , mpl::eval_if<
189                    is_same<Reference,use_default>
190                  , iterator_value<Base>
191                  , remove_reference<Reference>
192                >
193            >::type
194# else
195          , typename detail::ia_dflt_help<
196                Value, iterator_value<Base>
197            >::type
198# endif
199           
200          , typename detail::ia_dflt_help<
201                Traversal
202              , iterator_traversal<Base>
203            >::type
204
205          , typename detail::ia_dflt_help<
206                Reference
207              , mpl::eval_if<
208                    is_same<Value,use_default>
209                  , iterator_reference<Base>
210                  , add_reference<Value>
211                >
212            >::type
213
214          , typename detail::ia_dflt_help<
215                Difference, iterator_difference<Base>
216            >::type
217        >
218        type;
219    };
220 
221    // workaround for aC++ CR JAGaf33512
222    template <class Tr1, class Tr2>
223    inline void iterator_adaptor_assert_traversal ()
224    {
225      BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value));
226    }
227  }
228 
229  //
230  // Iterator Adaptor
231  //
232  // The parameter ordering changed slightly with respect to former
233  // versions of iterator_adaptor The idea is that when the user needs
234  // to fiddle with the reference type it is highly likely that the
235  // iterator category has to be adjusted as well.  Any of the
236  // following four template arguments may be ommitted or explicitly
237  // replaced by use_default.
238  //
239  //   Value - if supplied, the value_type of the resulting iterator, unless
240  //      const. If const, a conforming compiler strips constness for the
241  //      value_type. If not supplied, iterator_traits<Base>::value_type is used
242  //
243  //   Category - the traversal category of the resulting iterator. If not
244  //      supplied, iterator_traversal<Base>::type is used.
245  //
246  //   Reference - the reference type of the resulting iterator, and in
247  //      particular, the result type of operator*(). If not supplied but
248  //      Value is supplied, Value& is used. Otherwise
249  //      iterator_traits<Base>::reference is used.
250  //
251  //   Difference - the difference_type of the resulting iterator. If not
252  //      supplied, iterator_traits<Base>::difference_type is used.
253  //
254  template <
255      class Derived
256    , class Base
257    , class Value        = use_default
258    , class Traversal    = use_default
259    , class Reference    = use_default
260    , class Difference   = use_default
261  >
262  class iterator_adaptor
263    : public detail::iterator_adaptor_base<
264        Derived, Base, Value, Traversal, Reference, Difference
265      >::type
266  {
267      friend class iterator_core_access;
268
269   protected:
270      typedef typename detail::iterator_adaptor_base<
271          Derived, Base, Value, Traversal, Reference, Difference
272      >::type super_t;
273   public:
274      iterator_adaptor() {}
275
276      explicit iterator_adaptor(Base const &iter)
277          : m_iterator(iter)
278      {
279      }
280
281      typedef Base base_type;
282
283      Base const& base() const
284        { return m_iterator; }
285
286   protected:
287      // for convenience in derived classes
288      typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
289     
290      //
291      // lvalue access to the Base object for Derived
292      //
293      Base const& base_reference() const
294        { return m_iterator; }
295
296      Base& base_reference()
297        { return m_iterator; }
298
299   private:
300      //
301      // Core iterator interface for iterator_facade.  This is private
302      // to prevent temptation for Derived classes to use it, which
303      // will often result in an error.  Derived classes should use
304      // base_reference(), above, to get direct access to m_iterator.
305      //
306      typename super_t::reference dereference() const
307        { return *m_iterator; }
308
309      template <
310      class OtherDerived, class OtherIterator, class V, class C, class R, class D
311      >   
312      bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
313      {
314        // Maybe readd with same_distance
315        //           BOOST_STATIC_ASSERT(
316        //               (detail::same_category_and_difference<Derived,OtherDerived>::value)
317        //               );
318          return m_iterator == x.base();
319      }
320
321      typedef typename iterator_category_to_traversal<
322          typename super_t::iterator_category
323      >::type my_traversal;
324
325# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
326      detail::iterator_adaptor_assert_traversal<my_traversal, cat>();
327
328      void advance(typename super_t::difference_type n)
329      {
330          BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
331          m_iterator += n;
332      }
333 
334      void increment() { ++m_iterator; }
335
336      void decrement()
337      {
338          BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
339           --m_iterator;
340      }
341
342      template <
343          class OtherDerived, class OtherIterator, class V, class C, class R, class D
344      >   
345      typename super_t::difference_type distance_to(
346          iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
347      {
348          BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
349          // Maybe readd with same_distance
350          //           BOOST_STATIC_ASSERT(
351          //               (detail::same_category_and_difference<Derived,OtherDerived>::value)
352          //               );
353          return y.base() - m_iterator;
354      }
355
356# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
357     
358   private: // data members
359      Base m_iterator;
360  };
361
362} // namespace boost
363
364#include <boost/iterator/detail/config_undef.hpp>
365
366#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
Note: See TracBrowser for help on using the repository browser.