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