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