source: NonGTP/Boost/boost/iterator/counting_iterator.hpp @ 857

Revision 857, 6.3 KB checked in by igarcia, 19 years ago (diff)
Line 
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
15namespace boost {
16
17template <
18    class Incrementable
19  , class CategoryOrTraversal
20  , class Difference
21>
22class counting_iterator;
23
24namespace 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
144template <
145    class Incrementable
146  , class CategoryOrTraversal = use_default
147  , class Difference = use_default
148>
149class 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
204template <class Incrementable>
205inline counting_iterator<Incrementable>
206make_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
Note: See TracBrowser for help on using the repository browser.