]> git.lyx.org Git - lyx.git/blob - boost/boost/iterator/iterator_adaptor.hpp
* src/MenuBackend.[Ch]: the specialMenu is now a real menu, not a
[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 // 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
35 namespace 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