counting_iterator.hpp 7.4 KB

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