diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp index 3f5c3b4..5b8b6dc 100644 --- a/include/boost/integer.hpp +++ b/include/boost/integer.hpp @@ -7,6 +7,8 @@ // See http://www.boost.org/libs/integer for documentation. // Revision History +// 16 Jul 08 Added MPL-compatible variants of the minimum-size and value- +// based integer templates. (Daryle Walker) // 15 Jul 08 Added exact-integer templates; added MPL-compatible variant of // processor-optimized integer template. (Daryle Walker) // 14 Jul 08 Added extended-integer support. (Daryle Walker) @@ -255,6 +257,30 @@ namespace detail // MPL-compatible integer-mapping class templates ------------------------// + // minimum number of bits + template < int Bits, typename Signedness > + struct sized_integral + { + BOOST_STATIC_CONSTANT( bool, is_specialized = false ); + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + + template < int BitsIncludingSign > + struct sized_integral< BitsIncludingSign, signed > + : detail::integral_rank_to_type< + detail::int_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( int, bit_count = BitsIncludingSign ); + }; + + template < int Bits > + struct sized_integral< Bits, unsigned > + : detail::integral_rank_to_type< + detail::uint_rank_helper::rank, unsigned > + { + BOOST_STATIC_CONSTANT( int, bit_count = Bits ); + }; + // exact number of bits template < int Bits, typename Signedness > struct exact_integral @@ -279,17 +305,41 @@ namespace detail BOOST_STATIC_CONSTANT( int, bit_count = Bits ); }; + // maximum supported (positive) value, signed + template < intmax_t MaxValue > + struct maximum_signed_integral + : detail::integral_rank_to_type< + detail::int_max_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( intmax_t, bound = MaxValue ); + }; + + // minimum supported (negative) value + template < intmax_t MinValue > + struct minimum_signed_integral + : detail::integral_rank_to_type< + detail::int_min_rank_helper::rank, signed > + { + BOOST_STATIC_CONSTANT( intmax_t, bound = MinValue ); + }; + + // maximum supported (nonnegative) value, unsigned + template < uintmax_t Value > + struct maximum_unsigned_integral + : detail::integral_rank_to_type< + detail::uint_max_rank_helper::rank, unsigned > + { + BOOST_STATIC_CONSTANT( uintmax_t, bound = Value ); + }; + // integer templates specifying number of bits ---------------------------// // signed template< int Bits > // minimum bits (including sign) required struct int_t { - typedef typename detail::int_least_helper - < - detail::int_rank_helper::rank, - signed>::least least; - typedef typename int_fast_t::fast fast; + typedef typename sized_integral::type least; + typedef typename int_fast_t::fast fast; }; template< int Bits > // exact bits (including sign) desired @@ -302,11 +352,8 @@ namespace detail template< int Bits > // minimum bits required struct uint_t { - typedef typename detail::int_least_helper - < - detail::uint_rank_helper::rank, - unsigned>::least least; - typedef typename int_fast_t::fast fast; + typedef typename sized_integral::type least; + typedef typename int_fast_t::fast fast; // int_fast_t<> works correctly for unsigned too, in spite of the name. }; @@ -322,32 +369,23 @@ namespace detail template< intmax_t MaxValue > // maximum value to require support struct int_max_value_t { - typedef typename detail::int_least_helper - < - detail::int_max_rank_helper::rank, - signed>::least least; - typedef typename int_fast_t::fast fast; + typedef typename maximum_signed_integral::type least; + typedef typename int_fast_t::fast fast; }; template< intmax_t MinValue > // minimum value to require support struct int_min_value_t { - typedef typename detail::int_least_helper - < - detail::int_min_rank_helper::rank, - signed>::least least; - typedef typename int_fast_t::fast fast; + typedef typename minimum_signed_integral::type least; + typedef typename int_fast_t::fast fast; }; // unsigned template< uintmax_t Value > // maximum value to require support struct uint_value_t { - typedef typename detail::int_least_helper - < - detail::uint_max_rank_helper::rank, - unsigned>::least least; - typedef typename int_fast_t::fast fast; + typedef typename maximum_unsigned_integral::type least; + typedef typename int_fast_t::fast fast; }; diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp index 90102e8..1cc1ce1 100644 --- a/include/boost/integer_fwd.hpp +++ b/include/boost/integer_fwd.hpp @@ -90,9 +90,21 @@ template < typename BaseInt > template < typename LeastInt > struct int_fast_t; +template < int Bits, typename Signedness > + struct sized_integral; + template < int Bits, typename Signedness > struct exact_integral; +template < intmax_t MaxValue > + struct maximum_signed_integral; + +template < intmax_t MinValue > + struct minimum_signed_integral; + +template < uintmax_t Value > + struct maximum_unsigned_integral; + template< int Bits > struct int_t; diff --git a/integer.htm b/integer.htm index 6627935..e563bc1 100644 --- a/integer.htm +++ b/integer.htm @@ -53,6 +53,16 @@ namespace boost }; // MPL-compatible + template< int Bits, typename Signedness > + struct sized_integral + { + static bool const is_specialized = implementation_supplied; + static bool const is_signed = implementation_supplied; + static int const bit_count = Bits; + + typedef implementation_supplied type; + }; + template< int Bits, typename Signedness > struct exact_integral { @@ -63,12 +73,42 @@ namespace boost typedef implementation_supplied type; }; + template< intmax_t MaxValue > + struct maximum_signed_integral + { + static bool const is_specialized = implementation_supplied; + static bool const is_signed = true; + static intmax_t const bound = MaxValue; + + typedef implementation_supplied type; + }; + + template< intmax_t MinValue > + struct minimum_signed_integral + { + static bool const is_specialized = implementation_supplied; + static bool const is_signed = true; + static intmax_t const bound = MinValue; + + typedef implementation_supplied type; + }; + + template< uintmax_t Value > + struct maximum_unsigned_integral + { + static bool const is_specialized = implementation_supplied; + static bool const is_signed = false; + static uintmax_t const bound = Value; + + typedef implementation_supplied type; + }; + // signed template< int Bits > struct int_t { - typedef implementation_supplied least; - typedef int_fast_t<least>::fast fast; + typedef typename sized_integral<Bits, signed>::type least; + typedef int_fast_t<least>::fast fast; }; template< int Bits > @@ -81,8 +121,8 @@ namespace boost template< int Bits > struct uint_t { - typedef implementation_supplied least; - typedef int_fast_t<least>::fast fast; + typedef typename sized_integral<Bits, unsigned>::type least; + typedef int_fast_t<least>::fast fast; }; template< int Bits > @@ -95,23 +135,23 @@ namespace boost template< intmax_t MaxValue > struct int_max_value_t { - typedef implementation_supplied least; - typedef int_fast_t<least>::fast fast; + typedef typename maximum_signed_integral<MaxValue>::type least; + typedef int_fast_t<least>::fast fast; }; template< intmax_t MinValue > struct int_min_value_t { - typedef implementation_supplied least; - typedef int_fast_t<least>::fast fast; + typedef typename minimum_signed_integral<MinValue>::type least; + typedef int_fast_t<least>::fast fast; }; // unsigned template< uintmax_t Value > struct uint_value_t { - typedef implementation_supplied least; - typedef int_fast_t<least>::fast fast; + typedef typename maximum_unsigned_integral<Value>::type least; + typedef int_fast_t<least>::fast fast; }; } // namespace boost @@ -222,8 +262,10 @@ describes each template's criteria.

incompatible with template meta-programming techniques. -

The exact_integral class template provides an MPL-compatible -alternative. This alternative has the form:

+

The sized_integral, exact_integral, +maximum_signed_integral, minimum_signed_integral, and +maximum_unsigned_integral class templates provide MPL-compatible +alternatives. These alternatives generally have the form:

 template< SwitchType SwitchValue, typename Signedness >
@@ -299,6 +341,11 @@ struct name
 	
 
 
+

The exceptions are the extreme-value class templates +(maximum_signed_integral, minimum_signed_integral, and +maximum_unsigned_integral), which do not take a Signedness +template parameter because the meta-functions already inherently have signedness. +

The following table describes each template's criteria. The classic signed and unsigned equivalents are the sized-type class templates that each MPL-compatible class template emulates. (The setting of Signedness @@ -308,24 +355,66 @@ controls the appropriate emulation.)

Criteria for the MPL-Compatible Class Templates Class Template (all in name-space boost) - Parameter Type + Parameter Type (in name-space boost as needed) Parameter Member ID Classic Equivalent - Template Parameter Mapping (when type is defined) + Template Parameter Mapping (when type is defined) Signed Unsigned + + sized_integral + int + bit_count + int_t + uint_t + The smallest built-in integral type with at least + bit_count bits (including the sign bit when + Signedness is signed). Not present if no + type qualifies. + exact_integral int bit_count int_exact_t uint_exact_t - The smallest built-in integral type with exactly bit_count - bits (including the sign bit when Signedness is - signed). Not present if no type qualifies. + The smallest built-in integral type with exactly + bit_count bits (including the sign bit when + Signedness is signed). Not present if no + type qualifies. + + + maximum_signed_integral + intmax_t + bound + int_max_value_t + The smallest built-in integral type that can perserve the value in + bound. Not present if bound is non-positive. + It is possible for a type to be absent if + a platform supports really-extended integral types (beyond long + long or __int64), support for those types goes + into <boost/cstdint.hpp>, + but said support hadn't yet been added to <boost/integer.hpp> + + + minimum_signed_integral + intmax_t + bound + int_min_value_t + The smallest built-in integral type that can perserve the value in + bound. Not present if bound is non-negative. + + + maximum_unsigned_integral + uintmax_t + bound + uint_value_t + The smallest built-in integral type that can perserve the value in + bound. Should always be present. @@ -406,7 +495,7 @@ exact and value-based sized templates, and the MPL-compatible templates.


-

Revised July 15, 2008

+

Revised July 16, 2008

© Copyright Beman Dawes 1999. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file // for BOOST_MPL_ASSERT_RELATION, etc. #include // for boost::mpl::back #include // for boost::mpl::copy +#include // for boost::mpl::equal #include // for boost::mpl::front_inserter #include // for boost::mpl::integral_c #include // for boost::mpl::joint_view @@ -221,13 +223,53 @@ std::size_t const integral_type_count = sizeof(integral_bit_lengths) / // Use SFINAE to check if a particular bit-count is supported template < int Bits > bool -print_out_exact_signed( boost::mpl::integral_c const &x, int bits, - typename boost::exact_integral::type *unused = 0 ) +print_out_sized_signed( boost::mpl::integral_c const &x, int bits, + typename boost::sized_integral::type *unused = 0 ) { // Too bad the type-id expression couldn't use the compact form "*unused", // but type-ids of dereferenced null pointers throw by order of C++ 2003, // sect. 5.2.8, para. 2 (although the result is not conceptually needed). + PRIVATE_SHOW_MESSAGE( "There is a sized_integral<" << bits << + ", signed> specialization, with type '" << typeid(typename + boost::sized_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_sized_signed( T const &x, int bits ) +{ + PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << + ", signed> specialization." ); + return false; +} + +template < int Bits > +bool +print_out_sized_unsigned( boost::mpl::integral_c const &x, int bits, + typename boost::sized_integral::type *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a sized_integral<" << bits << + ", unsigned> specialization, with type '" << typeid(typename + boost::sized_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_sized_unsigned( T const &x, int bits ) +{ + PRIVATE_SHOW_MESSAGE( "There is no sized_integral<" << bits << + ", unsigned> specialization." ); + return false; +} + +template < int Bits > +bool +print_out_exact_signed( boost::mpl::integral_c const &x, int bits, + typename boost::exact_integral::type *unused = 0 ) +{ PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits << ", signed> specialization, with type '" << typeid(typename boost::exact_integral::type).name() << "'." ); @@ -263,6 +305,69 @@ print_out_exact_unsigned( T const &x, int bits ) return false; } +template < boost::intmax_t Value > +bool +print_out_maximum_signed( boost::maximum_signed_integral const &x, + boost::intmax_t value, typename boost::maximum_signed_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a maximum_signed_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::maximum_signed_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_maximum_signed( T const &x, boost::intmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no maximum_signed_integral<" << value << + "> specialization." ); + return false; +} + +template < boost::intmax_t Value > +bool +print_out_minimum_signed( boost::minimum_signed_integral const &x, + boost::intmax_t value, typename boost::minimum_signed_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a minimum_signed_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::minimum_signed_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_minimum_signed( T const &x, boost::intmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no minimum_signed_integral<" << value << + "> specialization." ); + return false; +} + +template < boost::uintmax_t Value > +bool +print_out_maximum_unsigned( boost::maximum_unsigned_integral const &x, + boost::uintmax_t value, typename boost::maximum_unsigned_integral::type + *unused = 0 ) +{ + PRIVATE_SHOW_MESSAGE( "There is a maximum_unsigned_integral<" << value << + "> specialization, with type '" << typeid(typename + boost::maximum_unsigned_integral::type).name() << "'." ); + return true; +} + +template < typename T > +bool +print_out_maximum_unsigned( T const &x, boost::uintmax_t value ) +{ + PRIVATE_SHOW_MESSAGE( "There is no maximum_unsigned_integral<" << value << + "> specialization." ); + return false; +} + } // unnamed namespace @@ -303,8 +408,18 @@ BOOST_AUTO_TEST_SUITE_END() // Check if given types can support given size parameters BOOST_AUTO_TEST_SUITE( show_type_tests ) -// Check the specialization type status of given bit lengths, exact or higher -BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, valid_bits_list ) +// Check the specialization type status of given bit lengths, minimum +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_lengths_test, T, bits_list ) +{ + BOOST_CHECK_EQUAL( print_out_sized_signed(T(), T::value), T::value <= + intmax_bits ); + BOOST_CHECK_EQUAL( print_out_sized_unsigned(T(), T::value), T::value <= + uintmax_bits ); +} + +// Check the classic specialization type status of given bit lengths, minimum +BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_lengths_test, T, + valid_bits_list ) { // This test is supposed to replace the following printouts given in // puesdo-code by: @@ -357,22 +472,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_unsigned_values_test, T, // length of a integral type, so 1 << N would have to fit in the next larger // type. (This is why N can't be more than bitlength(uintmax_t) - 1.) #ifndef BOOST_NO_USING_TEMPLATE - using boost::is_same; - using boost::uint_value_t; - using boost::uint_t; + using boost::mpl::equal; + using boost::maximum_unsigned_integral; + using boost::sized_integral; #else + using namespace boost::mpl; using namespace boost; #endif boost::uintmax_t const one = 1u; int const count = T::value; - BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename uint_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, - typename uint_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 2))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << (count - 1))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< maximum_unsigned_integral<(one << count)>, + sized_integral >) ); } // Check size comparisons of given value support, signed @@ -399,31 +515,32 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_signed_values_test, T, // type. (This is why N can't be more than bitlength(intmax_t) - 1. Note // that bitlength(intmax_t) + 1 == bitlength(uintmax_t).) #ifndef BOOST_NO_USING_TEMPLATE - using boost::is_same; - using boost::int_max_value_t; - using boost::int_t; - using boost::int_min_value_t; + using boost::mpl::equal; + using boost::maximum_signed_integral; + using boost::sized_integral; + using boost::minimum_signed_integral; #else + using namespace boost::mpl; using namespace boost; #endif boost::intmax_t const one = 1; int const count = T::value; - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 2))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 2))>, + sized_integral >) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << (count - 1))>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << (count - 1))>, + sized_integral >) ); - BOOST_MPL_ASSERT( (is_same::least, - typename int_t::least>::value) ); - BOOST_MPL_ASSERT( (is_same::least, - typename int_t::least>::value) ); + BOOST_MPL_ASSERT( (equal< maximum_signed_integral<+(one << count)>, + sized_integral >) ); + BOOST_MPL_ASSERT( (equal< minimum_signed_integral<-(one << count)>, + sized_integral >) ); } // Check the specialization type status of given bit lengths, exact only @@ -462,6 +579,88 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_exact_lengths_test, T, uint_exact_t::exact>::digits, ==, T::value ); } +// Check if MPL-compatible templates give bad returns for out-of-range values +BOOST_AUTO_TEST_CASE( show_not_type_for_parameter_test ) +{ +#ifndef BOOST_NO_USING_TEMPLATE + using boost::sized_integral; + using boost::mpl::integral_c; + using boost::exact_integral; + using boost::maximum_signed_integral; + using boost::minimum_signed_integral; + using boost::maximum_unsigned_integral; +#else + using namespace boost; + using namespace boost::mpl; +#endif + + typedef sized_integral< 3, signed> ssz3_type; + typedef sized_integral< 0, signed> ssz0_type; + typedef sized_integral<-3, signed> ssz3n_type; + + BOOST_CHECK( print_out_sized_signed(integral_c(), + ssz3_type::bit_count) ); + BOOST_CHECK( !print_out_sized_signed(integral_c(), + ssz0_type::bit_count) ); + BOOST_CHECK( !print_out_sized_signed(integral_c(), + ssz3n_type::bit_count) ); + + typedef sized_integral< 3, unsigned> usz3_type; + typedef sized_integral< 0, unsigned> usz0_type; + typedef sized_integral<-3, unsigned> usz3n_type; + + BOOST_CHECK( print_out_sized_unsigned(integral_c(), + usz3_type::bit_count) ); + BOOST_CHECK( print_out_sized_unsigned(integral_c(), + usz0_type::bit_count) ); + BOOST_CHECK( !print_out_sized_unsigned(integral_c(), + usz3n_type::bit_count) ); + + typedef exact_integral< 3, signed> se3_type; + typedef exact_integral< 0, signed> se0_type; + typedef exact_integral<-3, signed> se3n_type; + + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se3_type::bit_count) ); + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se0_type::bit_count) ); + BOOST_CHECK( !print_out_exact_signed(integral_c(), + se3n_type::bit_count) ); + + typedef exact_integral< 3, unsigned> ue3_type; + typedef exact_integral< 0, unsigned> ue0_type; + typedef exact_integral<-3, unsigned> ue3n_type; + + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue3_type::bit_count) ); + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue0_type::bit_count) ); + BOOST_CHECK( !print_out_exact_unsigned(integral_c(), + ue3n_type::bit_count) ); + + typedef maximum_signed_integral< 15> max15_type; + typedef maximum_signed_integral< 0> max0_type; + typedef maximum_signed_integral<-15> max15n_type; + + BOOST_CHECK( print_out_maximum_signed(max15_type(), max15_type::bound) ); + BOOST_CHECK( !print_out_maximum_signed(max0_type(), max0_type::bound) ); + BOOST_CHECK( !print_out_maximum_signed(max15n_type(), max15n_type::bound) ); + + typedef minimum_signed_integral< 15> min15_type; + typedef minimum_signed_integral< 0> min0_type; + typedef minimum_signed_integral<-15> min15n_type; + + BOOST_CHECK( !print_out_minimum_signed(min15_type(), min15_type::bound) ); + BOOST_CHECK( !print_out_minimum_signed(min0_type(), min0_type::bound) ); + BOOST_CHECK( print_out_minimum_signed(min15n_type(), min15n_type::bound) ); + + typedef maximum_unsigned_integral<15> umax15_type; + typedef maximum_unsigned_integral< 0> umax0_type; + + BOOST_CHECK( print_out_maximum_unsigned(umax15_type(), umax15_type::bound) ); + BOOST_CHECK( print_out_maximum_unsigned(umax0_type(), umax0_type::bound) ); +} + BOOST_AUTO_TEST_SUITE_END() // Check if given constants can fit in given types @@ -485,6 +684,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, // macros. The limit of type-lists is usually less than 32 (not to mention // 64) elements, so we have to take selected values. #ifndef BOOST_NO_USING_TEMPLATE + using boost::sized_integral; using boost::uint_t; using boost::int_t; #else @@ -497,7 +697,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, boost::intmax_t const value_s = intmax_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION () >> shift; - BOOST_CHECK_EQUAL( typename uint_t::least(value_u), value_u ); + BOOST_CHECK_EQUAL( (typename sized_integral::type(value_u)), + value_u ); BOOST_CHECK_EQUAL( typename uint_t::least(value_u >> 1), value_u >> 1 ); BOOST_CHECK_EQUAL( typename uint_t::fast(value_u), value_u ); @@ -505,8 +706,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T, >> 1 ); BOOST_CHECK_EQUAL( typename int_t::least(value_s), value_s ); - BOOST_CHECK_EQUAL( typename int_t::least(value_s >> 1), value_s - >> 1 ); + BOOST_CHECK_EQUAL( (typename sized_integral::type(value_s + >> 1)), value_s >> 1 ); BOOST_CHECK_EQUAL( typename int_t::fast(value_s), value_s ); BOOST_CHECK_EQUAL( typename int_t::fast(value_s >> 1), value_s >> 1 );