fix doc example typo
[boost.git] / boost / iterator / counting_iterator.hpp
blob1298a31f55d8efbc4923352dae9956036c5b4e6e
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>
15 namespace boost {
17 template <
18 class Incrementable
19 , class CategoryOrTraversal
20 , class Difference
22 class counting_iterator;
24 namespace detail
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
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);
38 # else
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
50 # endif
53 template <class T>
54 struct is_numeric
55 : mpl::bool_<(::boost::detail::is_numeric_impl<T>::value)>
56 {};
58 # if defined(BOOST_HAS_LONG_LONG)
59 template <>
60 struct is_numeric< ::boost::long_long_type>
61 : mpl::true_ {};
63 template <>
64 struct is_numeric< ::boost::ulong_long_type>
65 : mpl::true_ {};
66 # endif
68 // Some compilers fail to have a numeric_limits specialization
69 template <>
70 struct is_numeric<wchar_t>
71 : mpl::true_ {};
73 template <class 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<
85 CategoryOrTraversal
86 , mpl::eval_if<
87 is_numeric<Incrementable>
88 , mpl::identity<random_access_traversal_tag>
89 , iterator_traversal<Incrementable>
91 >::type traversal;
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>
100 >::type difference;
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;
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".
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)
129 return y - x;
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);
144 template <
145 class Incrementable
146 , class CategoryOrTraversal = use_default
147 , class Difference = use_default
149 class counting_iterator
150 : public detail::counting_iterator_base<
151 Incrementable, CategoryOrTraversal, Difference
152 >::type
154 typedef typename detail::counting_iterator_base<
155 Incrementable, CategoryOrTraversal, Difference
156 >::type super_t;
158 friend class iterator_core_access;
160 public:
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)
168 : super_t(x)
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
178 : super_t(t.base())
180 # endif
182 private:
184 typename super_t::reference dereference() const
186 return this->base_reference();
189 template <class OtherIncrementable>
190 difference_type
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>
197 >::type d;
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;
209 return result_t(x);
213 } // namespace boost::iterator
215 #endif // COUNTING_ITERATOR_DWA200348_HPP