]> git.lyx.org Git - lyx.git/blob - boost/boost/iterator/counting_iterator.hpp
Don't allow newline characters in document settings.
[lyx.git] / boost / boost / iterator / counting_iterator.hpp
1 // Copyright David Abrahams 2003.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef COUNTING_ITERATOR_DWA200348_HPP
6 # define COUNTING_ITERATOR_DWA200348_HPP
7
8 # include <boost/iterator/iterator_adaptor.hpp>
9 # include <boost/detail/numeric_traits.hpp>
10 # include <boost/mpl/bool.hpp>
11 # include <boost/mpl/if.hpp>
12 # include <boost/mpl/identity.hpp>
13 # include <boost/mpl/eval_if.hpp>
14
15 namespace boost {
16
17 template <
18     class Incrementable
19   , class CategoryOrTraversal
20   , class Difference
21 >
22 class counting_iterator;
23
24 namespace detail
25 {
26   // Try to detect numeric types at compile time in ways compatible
27   // with the limitations of the compiler and library.
28   template <class T>
29   struct is_numeric_impl
30   {
31       // For a while, this wasn't true, but we rely on it below. This is a regression assert.
32       BOOST_STATIC_ASSERT(::boost::is_integral<char>::value);
33       
34 # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
35       
36       BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<T>::is_specialized);
37       
38 # else
39       
40 #  if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
41       BOOST_STATIC_CONSTANT(
42           bool, value = (
43               boost::is_convertible<int,T>::value
44            && boost::is_convertible<T,int>::value
45       ));
46 #  else
47     BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic<T>::value);
48 #  endif
49       
50 # endif
51   };
52
53   template <class T>
54   struct is_numeric
55     : mpl::bool_<(::boost::detail::is_numeric_impl<T>::value)>
56   {};
57
58 #  if defined(BOOST_HAS_LONG_LONG)
59   template <>
60   struct is_numeric< ::boost::long_long_type>
61     : mpl::true_ {};
62   
63   template <>
64   struct is_numeric< ::boost::ulong_long_type>
65     : mpl::true_ {};
66 #  endif
67
68   // Some compilers fail to have a numeric_limits specialization
69   template <>
70   struct is_numeric<wchar_t>
71     : mpl::true_ {};
72   
73   template <class T>
74   struct numeric_difference
75   {
76       typedef typename boost::detail::numeric_traits<T>::difference_type type;
77   };
78
79   BOOST_STATIC_ASSERT(is_numeric<int>::value);
80   
81   template <class Incrementable, class CategoryOrTraversal, class Difference>
82   struct counting_iterator_base
83   {
84       typedef typename detail::ia_dflt_help<
85           CategoryOrTraversal
86         , mpl::eval_if<
87               is_numeric<Incrementable>
88             , mpl::identity<random_access_traversal_tag>
89             , iterator_traversal<Incrementable>
90           >
91       >::type traversal;
92       
93       typedef typename detail::ia_dflt_help<
94           Difference
95         , mpl::eval_if<
96               is_numeric<Incrementable>
97             , numeric_difference<Incrementable>
98             , iterator_difference<Incrementable>
99           >
100       >::type difference;
101       
102       typedef iterator_adaptor<
103           counting_iterator<Incrementable, CategoryOrTraversal, Difference> // self
104         , Incrementable                                           // Base
105         , Incrementable                                           // Value
106 # ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
107           const  // MSVC won't strip this.  Instead we enable Thomas'
108                  // criterion (see boost/iterator/detail/facade_iterator_category.hpp)
109 # endif 
110         , traversal
111         , Incrementable const&                                    // reference
112         , difference
113       > type;
114   };
115
116   // Template class distance_policy_select -- choose a policy for computing the
117   // distance between counting_iterators at compile-time based on whether or not
118   // the iterator wraps an integer or an iterator, using "poor man's partial
119   // specialization".
120
121   template <bool is_integer> struct distance_policy_select;
122
123   // A policy for wrapped iterators
124   template <class Difference, class Incrementable1, class Incrementable2>
125   struct iterator_distance
126   {
127       static Difference distance(Incrementable1 x, Incrementable2 y)
128       {
129           return y - x;
130       }
131   };
132
133   // A policy for wrapped numbers
134   template <class Difference, class Incrementable1, class Incrementable2>
135   struct number_distance
136   {
137       static Difference distance(Incrementable1 x, Incrementable2 y)
138       {
139           return numeric_distance(x, y);
140       }
141   };
142 }
143
144 template <
145     class Incrementable
146   , class CategoryOrTraversal = use_default
147   , class Difference = use_default
148 >
149 class counting_iterator
150   : public detail::counting_iterator_base<
151         Incrementable, CategoryOrTraversal, Difference
152     >::type
153 {
154     typedef typename detail::counting_iterator_base<
155         Incrementable, CategoryOrTraversal, Difference
156     >::type super_t;
157     
158     friend class iterator_core_access;
159
160  public:
161     typedef typename super_t::difference_type difference_type;
162
163     counting_iterator() { }
164     
165     counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {}
166
167     counting_iterator(Incrementable x)
168       : super_t(x)
169     {
170     }
171
172 # if 0
173     template<class OtherIncrementable>
174     counting_iterator(
175         counting_iterator<OtherIncrementable, CategoryOrTraversal, Difference> const& t
176       , typename enable_if_convertible<OtherIncrementable, Incrementable>::type* = 0
177     )
178       : super_t(t.base())
179     {}
180 # endif 
181
182  private:
183     
184     typename super_t::reference dereference() const
185     {
186         return this->base_reference();
187     }
188
189     template <class OtherIncrementable>
190     difference_type
191     distance_to(counting_iterator<OtherIncrementable, CategoryOrTraversal, Difference> const& y) const
192     {
193       typedef typename mpl::if_<
194           detail::is_numeric<Incrementable>
195         , detail::number_distance<difference_type, Incrementable, OtherIncrementable>
196         , detail::iterator_distance<difference_type, Incrementable, OtherIncrementable>
197       >::type d;
198
199       return d::distance(this->base(), y.base());
200     }
201 };
202
203 // Manufacture a counting iterator for an arbitrary incrementable type
204 template <class Incrementable>
205 inline counting_iterator<Incrementable>
206 make_counting_iterator(Incrementable x)
207 {
208   typedef counting_iterator<Incrementable> result_t;
209   return result_t(x);
210 }
211
212
213 } // namespace boost::iterator
214
215 #endif // COUNTING_ITERATOR_DWA200348_HPP