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