diff --git a/include/boost/detail/numeric_traits.hpp b/include/boost/detail/numeric_traits.hpp index 2f97ebf..a62affb 100644 --- a/include/boost/detail/numeric_traits.hpp +++ b/include/boost/detail/numeric_traits.hpp @@ -56,65 +56,39 @@ // 21 Jan 2001 - Created (David Abrahams) #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 -# define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 +#define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#include +#include +#endif 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 - struct is_signed - { -#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) - BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0))); -#else - BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_signed); -#endif - }; - -# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#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 struct digit_traits_select; - - // numeric_limits is specialized; just select that version of digits - template <> struct digit_traits_select + // for some integer types, like __int128 in libstdc++ (gcc). + template ::is_specialized> + struct digit_traits { - template struct traits - { - BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits::digits); - }; + BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits::digits); }; // numeric_limits is not specialized; compute digits from sizeof(T) - template <> struct digit_traits_select + template + struct digit_traits { - template struct traits - { - BOOST_STATIC_CONSTANT(int, digits = ( - sizeof(T) * std::numeric_limits::digits - - (is_signed::value ? 1 : 0)) - ); - }; - }; - - // here's the "usable" template - template struct digit_traits - { - typedef digit_traits_select< - ::std::numeric_limits::is_specialized> selector; - typedef typename selector::template traits traits; - BOOST_STATIC_CONSTANT(int, digits = traits::digits); + BOOST_STATIC_CONSTANT(int, digits = ( + sizeof(T) * std::numeric_limits::digits + - (boost::is_signed::value ? 1 : 0)) + ); }; #endif @@ -124,44 +98,48 @@ namespace boost { namespace detail { template struct integer_traits { -# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS private: typedef Integer integer_type; typedef std::numeric_limits x; 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::digits)))>::template then< + typedef typename boost::conditional< + (int(x::is_signed) + && (!int(x::is_bounded) + // digits is the number of no-sign bits + || (int(x::digits) + 1 >= digit_traits::digits))), Integer, - - typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< - signed int, - typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< - signed long, + typename boost::conditional< + (int(x::digits) + 1 < digit_traits::digits), + signed int, - // else - intmax_t - >::type>::type>::type difference_type; + typename boost::conditional< + (int(x::digits) + 1 < digit_traits::digits), + signed long, + boost::intmax_t + >::type + >::type + >::type difference_type; #else BOOST_STATIC_ASSERT(boost::is_integral::value); - typedef typename - if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then< - - typename if_true<(is_signed::value)>::template then< - Integer, - intmax_t - >::type, + typedef typename boost::conditional< + (sizeof(Integer) >= sizeof(intmax_t)), - typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then< + boost::conditional< + (boost::is_signed::value), + Integer, + boost::intmax_t + >, + + boost::conditional< + (sizeof(Integer) < sizeof(std::ptrdiff_t)), std::ptrdiff_t, - intmax_t - >::type - >::type difference_type; -# endif + boost::intmax_t + > + >::type::type difference_type; +#endif }; // Right now, only supports integers, but should be expanded. @@ -172,7 +150,7 @@ namespace boost { namespace detail { }; template - typename numeric_traits::difference_type numeric_distance(Number x, Number y) + inline BOOST_CONSTEXPR typename numeric_traits::difference_type numeric_distance(Number x, Number y) { typedef typename numeric_traits::difference_type difference_type; return difference_type(y) - difference_type(x); diff --git a/test/numeric_traits_test.cpp b/test/numeric_traits_test.cpp index ffd301c..c22cc6f 100644 --- a/test/numeric_traits_test.cpp +++ b/test/numeric_traits_test.cpp @@ -17,17 +17,18 @@ #include #include -#include +#include +#include +#include #include #include -#include -#include #include #include #include +#include #include #ifndef BOOST_NO_LIMITS -# include +#include #endif // ================================================================================= @@ -42,7 +43,7 @@ template struct complement; // forward // The template complement, below, does all the real work, using "poor man's // partial specialization". We need complement_traits_aux<> so that MSVC doesn't -// complain about undefined min/max as we're trying to recursively define them. +// complain about undefined min/max as we're trying to recursively define them. template struct complement_traits_aux { @@ -109,7 +110,7 @@ struct complement<1> template struct traits { - BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed::value); + BOOST_STATIC_CONSTANT(bool, is_signed = boost::is_signed::value); BOOST_STATIC_CONSTANT(Number, min = complement_base::template values::min); BOOST_STATIC_CONSTANT(Number, max = @@ -184,21 +185,30 @@ template <> struct promote { std::string static from(const boost::uintmax_t x) { if (x > ULONG_MAX) return std::string("large unsigned value"); - else - return boost::lexical_cast((unsigned long)x); + else { + std::ostringstream strm; + strm << (unsigned long)x; + return strm.str(); + } } }; template <> struct promote { std::string static from(const boost::intmax_t x) { if (x > boost::intmax_t(ULONG_MAX)) return std::string("large positive signed value"); - else if (x >= 0) - return boost::lexical_cast((unsigned long)x); - + else if (x >= 0) { + std::ostringstream strm; + strm << (unsigned long)x; + return strm.str(); + } + if (x < boost::intmax_t(LONG_MIN)) return std::string("large negative signed value"); - else - return boost::lexical_cast((long)x); + else { + std::ostringstream strm; + strm << (long)x; + return strm.str(); + } } }; #endif @@ -225,7 +235,7 @@ template void test_aux(unsigned_tag, Number*) { typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(!boost::detail::is_signed::value); + BOOST_STATIC_ASSERT(!boost::is_signed::value); BOOST_STATIC_ASSERT( (sizeof(Number) < sizeof(boost::intmax_t)) | (boost::is_same::value)); @@ -242,7 +252,7 @@ void test_aux(unsigned_tag, Number*) const Number max = complement_traits::max; const Number min = complement_traits::min; - + const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t)) ? max : max / 2 - 1; @@ -251,10 +261,10 @@ void test_aux(unsigned_tag, Number*) << stream_number(max) << "..." << std::flush; std::cout << "difference_type = " << typeid(difference_type).name() << "..." << std::flush; - + difference_type d1 = boost::detail::numeric_distance(Number(0), test_max); difference_type d2 = boost::detail::numeric_distance(test_max, Number(0)); - + std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; " << std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush; @@ -272,11 +282,11 @@ struct in_range_tag {}; template void signed_test(in_range_tag, Number*) { - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); + BOOST_STATIC_ASSERT(boost::is_signed::value); typedef typename boost::detail::numeric_traits::difference_type difference_type; const Number max = complement_traits::max; const Number min = complement_traits::min; - + difference_type d1 = boost::detail::numeric_distance(min, max); difference_type d2 = boost::detail::numeric_distance(max, min); @@ -293,7 +303,7 @@ void signed_test(in_range_tag, Number*) template void signed_test(out_of_range_tag, Number*) { - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); + BOOST_STATIC_ASSERT(boost::is_signed::value); typedef typename boost::detail::numeric_traits::difference_type difference_type; const Number max = complement_traits::max; const Number min = complement_traits::min; @@ -318,7 +328,7 @@ template void test_aux(signed_tag, Number*) { typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); + BOOST_STATIC_ASSERT(boost::is_signed::value); BOOST_STATIC_ASSERT( (sizeof(Number) < sizeof(boost::intmax_t)) | (boost::is_same::value)); @@ -331,22 +341,20 @@ void test_aux(signed_tag, Number*) // Force casting to Number here to work around the fact that it's an enum on MSVC BOOST_STATIC_ASSERT(Number(complement_traits::max) > Number(0)); BOOST_STATIC_ASSERT(Number(complement_traits::min) < Number(0)); -#endif +#endif const Number max = complement_traits::max; const Number min = complement_traits::min; - + std::cout << std::hex << "min = " << stream_number(min) << ", max = " << stream_number(max) << "..." << std::flush; std::cout << "difference_type = " << typeid(difference_type).name() << "..." << std::flush; - typedef typename boost::detail::if_true< - (sizeof(Number) < sizeof(boost::intmax_t))> - ::template then< - in_range_tag, - out_of_range_tag - >::type - range_tag; + typedef typename boost::conditional< + (sizeof(Number) < sizeof(boost::intmax_t)), + in_range_tag, + out_of_range_tag + >::type range_tag; signed_test(range_tag(), 0); } @@ -365,7 +373,7 @@ void test(Number* = 0) << "..." << std::flush; // factoring out difference_type for the assert below confused Borland :( - typedef boost::detail::is_signed< + typedef boost::is_signed< #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 typename #endif @@ -373,10 +381,12 @@ void test(Number* = 0) > is_signed; BOOST_STATIC_ASSERT(is_signed::value); - typedef typename boost::detail::if_true< - boost::detail::is_signed::value - >::template then::type signedness; - + typedef typename boost::conditional< + boost::is_signed::value, + signed_tag, + unsigned_tag + >::type signedness; + test_aux(signedness(), 0); std::cout << "passed" << std::endl; }