| // (C) Copyright David Abrahams 2001, Howard Hinnant 2001. |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // Template class numeric_traits<Number> -- |
| // |
| // Supplies: |
| // |
| // typedef difference_type -- a type used to represent the difference |
| // between any two values of Number. |
| // |
| // Support: |
| // 1. Not all specializations are supplied |
| // |
| // 2. Use of specializations that are not supplied will cause a |
| // compile-time error |
| // |
| // 3. Users are free to specialize numeric_traits for any type. |
| // |
| // 4. Right now, specializations are only supplied for integer types. |
| // |
| // 5. On implementations which do not supply compile-time constants in |
| // std::numeric_limits<>, only specializations for built-in integer types |
| // are supplied. |
| // |
| // 6. Handling of numbers whose range of representation is at least as |
| // great as boost::intmax_t can cause some differences to be |
| // unrepresentable in difference_type: |
| // |
| // Number difference_type |
| // ------ --------------- |
| // signed Number |
| // unsigned intmax_t |
| // |
| // template <class Number> typename numeric_traits<Number>::difference_type |
| // numeric_distance(Number x, Number y) |
| // computes (y - x), attempting to avoid overflows. |
| // |
| |
| // See http://www.boost.org for most recent version including documentation. |
| |
| // Revision History |
| // 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams) |
| // 11 Feb 2001 - Rolled back ineffective Borland-specific code |
| // (David Abrahams) |
| // 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but |
| // not seeing any improvement yet (David Abrahams) |
| // 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp |
| // (David Abrahams) |
| // 23 Jan 2001 - Fixed logic of difference_type selection, which was |
| // completely wack. In the process, added digit_traits<> |
| // to compute the number of digits in intmax_t even when |
| // not supplied by numeric_limits<>. (David Abrahams) |
| // 21 Jan 2001 - Created (David Abrahams) |
| |
| #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 |
| # define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 |
| |
| # include <boost/config.hpp> |
| # include <boost/cstdint.hpp> |
| # include <boost/static_assert.hpp> |
| # include <boost/type_traits.hpp> |
| # include <boost/detail/select_type.hpp> |
| # include <boost/limits.hpp> |
| |
| namespace boost { namespace detail { |
| |
| // Template class is_signed -- determine whether a numeric type is signed |
| // Requires that T is constructable from the literals -1 and 0. Compile-time |
| // error results if that requirement is not met (and thus signedness is not |
| // likely to have meaning for that type). |
| template <class Number> |
| struct is_signed |
| { |
| #if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300 |
| BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0))); |
| #else |
| BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<Number>::is_signed); |
| #endif |
| }; |
| |
| # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
| // digit_traits - compute the number of digits in a built-in integer |
| // type. Needed for implementations on which numeric_limits is not specialized |
| // for intmax_t (e.g. VC6). |
| template <bool is_specialized> struct digit_traits_select; |
| |
| // numeric_limits is specialized; just select that version of digits |
| template <> struct digit_traits_select<true> |
| { |
| template <class T> struct traits |
| { |
| BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits<T>::digits); |
| }; |
| }; |
| |
| // numeric_limits is not specialized; compute digits from sizeof(T) |
| template <> struct digit_traits_select<false> |
| { |
| template <class T> struct traits |
| { |
| BOOST_STATIC_CONSTANT(int, digits = ( |
| sizeof(T) * std::numeric_limits<unsigned char>::digits |
| - (is_signed<T>::value ? 1 : 0)) |
| ); |
| }; |
| }; |
| |
| // here's the "usable" template |
| template <class T> struct digit_traits |
| { |
| typedef digit_traits_select< |
| ::std::numeric_limits<T>::is_specialized> selector; |
| typedef typename selector::template traits<T> traits; |
| BOOST_STATIC_CONSTANT(int, digits = traits::digits); |
| }; |
| #endif |
| |
| // Template class integer_traits<Integer> -- traits of various integer types |
| // This should probably be rolled into boost::integer_traits one day, but I |
| // need it to work without <limits> |
| template <class Integer> |
| struct integer_traits |
| { |
| # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS |
| private: |
| typedef Integer integer_type; |
| typedef std::numeric_limits<integer_type> x; |
| # if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 |
| // for some reason, MSVC asserts when it shouldn't unless we make these |
| // local definitions |
| BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer); |
| BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized); |
| |
| BOOST_STATIC_ASSERT(is_integer); |
| BOOST_STATIC_ASSERT(is_specialized); |
| # endif |
| public: |
| typedef typename |
| if_true<(int(x::is_signed) |
| && (!int(x::is_bounded) |
| // digits is the number of no-sign bits |
| || (int(x::digits) + 1 >= digit_traits<boost::intmax_t>::digits)))>::template then< |
| Integer, |
| |
| typename if_true<(int(x::digits) + 1 < digit_traits<signed int>::digits)>::template then< |
| signed int, |
| |
| typename if_true<(int(x::digits) + 1 < digit_traits<signed long>::digits)>::template then< |
| signed long, |
| |
| // else |
| intmax_t |
| >::type>::type>::type difference_type; |
| #else |
| BOOST_STATIC_ASSERT(boost::is_integral<Integer>::value); |
| |
| typedef typename |
| if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then< |
| |
| typename if_true<(is_signed<Integer>::value)>::template then< |
| Integer, |
| intmax_t |
| >::type, |
| |
| typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then< |
| std::ptrdiff_t, |
| intmax_t |
| >::type |
| >::type difference_type; |
| # endif |
| }; |
| |
| // Right now, only supports integers, but should be expanded. |
| template <class Number> |
| struct numeric_traits |
| { |
| typedef typename integer_traits<Number>::difference_type difference_type; |
| }; |
| |
| template <class Number> |
| typename numeric_traits<Number>::difference_type numeric_distance(Number x, Number y) |
| { |
| typedef typename numeric_traits<Number>::difference_type difference_type; |
| return difference_type(y) - difference_type(x); |
| } |
| }} |
| |
| #endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901 |