next_prior.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Boost next_prior.hpp header file ---------------------------------------//
  2. // (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/utility for documentation.
  6. // Revision History
  7. // 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker)
  8. #ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
  9. #define BOOST_NEXT_PRIOR_HPP_INCLUDED
  10. #include <iterator>
  11. #if defined(_MSC_VER) && _MSC_VER <= 1310
  12. #include <boost/mpl/and.hpp>
  13. #include <boost/type_traits/is_integral.hpp>
  14. #endif
  15. #include <boost/type_traits/is_unsigned.hpp>
  16. #include <boost/type_traits/integral_promotion.hpp>
  17. #include <boost/type_traits/make_signed.hpp>
  18. #include <boost/type_traits/has_plus.hpp>
  19. #include <boost/type_traits/has_plus_assign.hpp>
  20. #include <boost/type_traits/has_minus.hpp>
  21. #include <boost/type_traits/has_minus_assign.hpp>
  22. namespace boost {
  23. // Helper functions for classes like bidirectional iterators not supporting
  24. // operator+ and operator-
  25. //
  26. // Usage:
  27. // const std::list<T>::iterator p = get_some_iterator();
  28. // const std::list<T>::iterator prev = boost::prior(p);
  29. // const std::list<T>::iterator next = boost::next(prev, 2);
  30. // Contributed by Dave Abrahams
  31. namespace next_prior_detail {
  32. template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value >
  33. struct next_impl2
  34. {
  35. static T call(T x, Distance n)
  36. {
  37. std::advance(x, n);
  38. return x;
  39. }
  40. };
  41. template< typename T, typename Distance >
  42. struct next_impl2< T, Distance, true >
  43. {
  44. static T call(T x, Distance n)
  45. {
  46. return x + n;
  47. }
  48. };
  49. template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value >
  50. struct next_impl1 :
  51. public next_impl2< T, Distance >
  52. {
  53. };
  54. template< typename T, typename Distance >
  55. struct next_impl1< T, Distance, true >
  56. {
  57. static T call(T x, Distance n)
  58. {
  59. x += n;
  60. return x;
  61. }
  62. };
  63. template<
  64. typename T,
  65. typename Distance,
  66. typename PromotedDistance = typename integral_promotion< Distance >::type,
  67. #if !defined(_MSC_VER) || _MSC_VER > 1310
  68. bool IsUInt = is_unsigned< PromotedDistance >::value
  69. #else
  70. // MSVC 7.1 has problems with applying is_unsigned to non-integral types
  71. bool IsUInt = mpl::and_< is_integral< PromotedDistance >, is_unsigned< PromotedDistance > >::value
  72. #endif
  73. >
  74. struct prior_impl3
  75. {
  76. static T call(T x, Distance n)
  77. {
  78. std::advance(x, -n);
  79. return x;
  80. }
  81. };
  82. template< typename T, typename Distance, typename PromotedDistance >
  83. struct prior_impl3< T, Distance, PromotedDistance, true >
  84. {
  85. static T call(T x, Distance n)
  86. {
  87. typedef typename make_signed< PromotedDistance >::type signed_distance;
  88. std::advance(x, -static_cast< signed_distance >(static_cast< PromotedDistance >(n)));
  89. return x;
  90. }
  91. };
  92. template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value >
  93. struct prior_impl2 :
  94. public prior_impl3< T, Distance >
  95. {
  96. };
  97. template< typename T, typename Distance >
  98. struct prior_impl2< T, Distance, true >
  99. {
  100. static T call(T x, Distance n)
  101. {
  102. return x - n;
  103. }
  104. };
  105. template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value >
  106. struct prior_impl1 :
  107. public prior_impl2< T, Distance >
  108. {
  109. };
  110. template< typename T, typename Distance >
  111. struct prior_impl1< T, Distance, true >
  112. {
  113. static T call(T x, Distance n)
  114. {
  115. x -= n;
  116. return x;
  117. }
  118. };
  119. } // namespace next_prior_detail
  120. template <class T>
  121. inline T next(T x) { return ++x; }
  122. template <class T, class Distance>
  123. inline T next(T x, Distance n)
  124. {
  125. return next_prior_detail::next_impl1< T, Distance >::call(x, n);
  126. }
  127. template <class T>
  128. inline T prior(T x) { return --x; }
  129. template <class T, class Distance>
  130. inline T prior(T x, Distance n)
  131. {
  132. return next_prior_detail::prior_impl1< T, Distance >::call(x, n);
  133. }
  134. } // namespace boost
  135. #endif // BOOST_NEXT_PRIOR_HPP_INCLUDED