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
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>
19 , class CategoryOrTraversal
22 class counting_iterator
;
26 // Try to detect numeric types at compile time in ways compatible
27 // with the limitations of the compiler and library.
29 struct is_numeric_impl
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
);
34 # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
36 BOOST_STATIC_CONSTANT(bool, value
= std::numeric_limits
<T
>::is_specialized
);
40 # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
41 BOOST_STATIC_CONSTANT(
43 boost::is_convertible
<int,T
>::value
44 && boost::is_convertible
<T
,int>::value
47 BOOST_STATIC_CONSTANT(bool, value
= ::boost::is_arithmetic
<T
>::value
);
55 : mpl::bool_
<(::boost::detail::is_numeric_impl
<T
>::value
)>
58 # if defined(BOOST_HAS_LONG_LONG)
60 struct is_numeric
< ::boost::long_long_type
>
64 struct is_numeric
< ::boost::ulong_long_type
>
68 // Some compilers fail to have a numeric_limits specialization
70 struct is_numeric
<wchar_t>
74 struct numeric_difference
76 typedef typename
boost::detail::numeric_traits
<T
>::difference_type type
;
79 BOOST_STATIC_ASSERT(is_numeric
<int>::value
);
81 template <class Incrementable
, class CategoryOrTraversal
, class Difference
>
82 struct counting_iterator_base
84 typedef typename
detail::ia_dflt_help
<
87 is_numeric
<Incrementable
>
88 , mpl::identity
<random_access_traversal_tag
>
89 , iterator_traversal
<Incrementable
>
93 typedef typename
detail::ia_dflt_help
<
96 is_numeric
<Incrementable
>
97 , numeric_difference
<Incrementable
>
98 , iterator_difference
<Incrementable
>
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)
111 , Incrementable
const& // reference
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
121 template <bool is_integer
> struct distance_policy_select
;
123 // A policy for wrapped iterators
124 template <class Difference
, class Incrementable1
, class Incrementable2
>
125 struct iterator_distance
127 static Difference
distance(Incrementable1 x
, Incrementable2 y
)
133 // A policy for wrapped numbers
134 template <class Difference
, class Incrementable1
, class Incrementable2
>
135 struct number_distance
137 static Difference
distance(Incrementable1 x
, Incrementable2 y
)
139 return numeric_distance(x
, y
);
146 , class CategoryOrTraversal
= use_default
147 , class Difference
= use_default
149 class counting_iterator
150 : public detail::counting_iterator_base
<
151 Incrementable
, CategoryOrTraversal
, Difference
154 typedef typename
detail::counting_iterator_base
<
155 Incrementable
, CategoryOrTraversal
, Difference
158 friend class iterator_core_access
;
161 typedef typename
super_t::difference_type difference_type
;
163 counting_iterator() { }
165 counting_iterator(counting_iterator
const& rhs
) : super_t(rhs
.base()) {}
167 counting_iterator(Incrementable x
)
173 template<class OtherIncrementable
>
175 counting_iterator
<OtherIncrementable
, CategoryOrTraversal
, Difference
> const& t
176 , typename enable_if_convertible
<OtherIncrementable
, Incrementable
>::type
* = 0
184 typename
super_t::reference
dereference() const
186 return this->base_reference();
189 template <class OtherIncrementable
>
191 distance_to(counting_iterator
<OtherIncrementable
, CategoryOrTraversal
, Difference
> const& y
) const
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
>
199 return d::distance(this->base(), y
.base());
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
)
208 typedef counting_iterator
<Incrementable
> result_t
;
213 } // namespace boost::iterator
215 #endif // COUNTING_ITERATOR_DWA200348_HPP