diff options
Diffstat (limited to 'boost/next_prior.hpp')
-rw-r--r-- | boost/next_prior.hpp | 122 |
1 files changed, 118 insertions, 4 deletions
diff --git a/boost/next_prior.hpp b/boost/next_prior.hpp index e1d2e42891..7854ec436a 100644 --- a/boost/next_prior.hpp +++ b/boost/next_prior.hpp @@ -13,6 +13,17 @@ #define BOOST_NEXT_PRIOR_HPP_INCLUDED #include <iterator> +#if defined(_MSC_VER) && _MSC_VER <= 1310 +#include <boost/mpl/and.hpp> +#include <boost/type_traits/is_integral.hpp> +#endif +#include <boost/type_traits/is_unsigned.hpp> +#include <boost/type_traits/integral_promotion.hpp> +#include <boost/type_traits/make_signed.hpp> +#include <boost/type_traits/has_plus.hpp> +#include <boost/type_traits/has_plus_assign.hpp> +#include <boost/type_traits/has_minus.hpp> +#include <boost/type_traits/has_minus_assign.hpp> namespace boost { @@ -26,14 +37,118 @@ namespace boost { // Contributed by Dave Abrahams +namespace next_prior_detail { + +template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value > +struct next_impl2 +{ + static T call(T x, Distance n) + { + std::advance(x, n); + return x; + } +}; + +template< typename T, typename Distance > +struct next_impl2< T, Distance, true > +{ + static T call(T x, Distance n) + { + return x + n; + } +}; + + +template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value > +struct next_impl1 : + public next_impl2< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct next_impl1< T, Distance, true > +{ + static T call(T x, Distance n) + { + x += n; + return x; + } +}; + + +template< + typename T, + typename Distance, + typename PromotedDistance = typename integral_promotion< Distance >::type, +#if !defined(_MSC_VER) || _MSC_VER > 1310 + bool IsUInt = is_unsigned< PromotedDistance >::value +#else + // MSVC 7.1 has problems with applying is_unsigned to non-integral types + bool IsUInt = mpl::and_< is_integral< PromotedDistance >, is_unsigned< PromotedDistance > >::value +#endif +> +struct prior_impl3 +{ + static T call(T x, Distance n) + { + std::advance(x, -n); + return x; + } +}; + +template< typename T, typename Distance, typename PromotedDistance > +struct prior_impl3< T, Distance, PromotedDistance, true > +{ + static T call(T x, Distance n) + { + typedef typename make_signed< PromotedDistance >::type signed_distance; + std::advance(x, -static_cast< signed_distance >(static_cast< PromotedDistance >(n))); + return x; + } +}; + + +template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value > +struct prior_impl2 : + public prior_impl3< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct prior_impl2< T, Distance, true > +{ + static T call(T x, Distance n) + { + return x - n; + } +}; + + +template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value > +struct prior_impl1 : + public prior_impl2< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct prior_impl1< T, Distance, true > +{ + static T call(T x, Distance n) + { + x -= n; + return x; + } +}; + +} // namespace next_prior_detail + template <class T> inline T next(T x) { return ++x; } template <class T, class Distance> inline T next(T x, Distance n) { - std::advance(x, n); - return x; + return next_prior_detail::next_impl1< T, Distance >::call(x, n); } template <class T> @@ -42,8 +157,7 @@ inline T prior(T x) { return --x; } template <class T, class Distance> inline T prior(T x, Distance n) { - std::advance(x, -n); - return x; + return next_prior_detail::prior_impl1< T, Distance >::call(x, n); } } // namespace boost |