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