|
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 |