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