diff --git a/include/boost/integer.hpp b/include/boost/integer.hpp
index cb285f8..a976e3b 100644
--- a/include/boost/integer.hpp
+++ b/include/boost/integer.hpp
@@ -7,6 +7,7 @@
// See http://www.boost.org/libs/integer for documentation.
// Revision History
+// 15 Jul 08 Added exact-integer templates. (Daryle Walker)
// 14 Jul 08 Added extended-integer support. (Daryle Walker)
// 13 Jul 08 Redid implmentation. (Daryle Walker)
// 22 Sep 01 Added value-based integer templates. (Daryle Walker)
@@ -24,6 +25,8 @@
#include // for boost::integer_traits
#include // for std::numeric_limits
+#include // for UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, etc.
+
namespace boost
{
@@ -85,7 +88,7 @@ namespace detail
struct int_rank_helper
{
BOOST_STATIC_CONSTANT( int, mantissa = BitsIncludingSign - 1 );
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (BitsIncludingSign > 0) * (
#ifdef BOOST_HAS_LONG_LONG
(mantissa <= std::numeric_limits< long_long_type >::digits) +
#elif defined(BOOST_HAS_MS_INT64)
@@ -96,13 +99,13 @@ namespace detail
(mantissa <= std::numeric_limits< long >::digits) +
(mantissa <= std::numeric_limits< int >::digits) +
(mantissa <= std::numeric_limits< short >::digits) +
- (mantissa <= std::numeric_limits< signed char >::digits) );
+ (mantissa <= std::numeric_limits< signed char >::digits)) );
};
template < int Bits >
struct uint_rank_helper
{
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (Bits >= 0) * (
#ifdef BOOST_HAS_LONG_LONG
(Bits <= std::numeric_limits< ulong_long_type >::digits) +
#elif defined(BOOST_HAS_MS_INT64)
@@ -113,14 +116,53 @@ namespace detail
(Bits <= std::numeric_limits< unsigned long >::digits) +
(Bits <= std::numeric_limits< unsigned int >::digits) +
(Bits <= std::numeric_limits< unsigned short >::digits) +
- (Bits <= std::numeric_limits< unsigned char >::digits) );
+ (Bits <= std::numeric_limits< unsigned char >::digits)) );
};
+ template < int BitsIncludingSign >
+ struct int_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); };
+ template < int Bits >
+ struct uint_exact_rank_helper { BOOST_STATIC_CONSTANT( int, rank = 0 ); };
+
+#define BOOST_PRIVATE_INT_EXACT_BUILDER(Type, Rank) \
+ template < > \
+ struct int_exact_rank_helper::digits + 1> \
+ { BOOST_STATIC_CONSTANT( int, rank = Rank ); }
+#define BOOST_PRIVATE_UINT_EXACT_BUILDER(Type, Rank) \
+ template < > \
+ struct uint_exact_rank_helper::digits> \
+ { BOOST_STATIC_CONSTANT( int, rank = Rank ); }
+
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
+ BOOST_PRIVATE_INT_EXACT_BUILDER( long_long_type, 1 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( ulong_long_type, 1 );
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
+ BOOST_PRIVATE_INT_EXACT_BUILDER( __int64, 1 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned __int64, 1 );
+#endif
+#if ULONG_MAX > UINT_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( long, 2 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned long, 2 );
+#endif
+#if UINT_MAX > USHRT_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( int, 3 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned, 3 );
+#endif
+#if USHRT_MAX > UCHAR_MAX
+ BOOST_PRIVATE_INT_EXACT_BUILDER( short, 4 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned short, 4 );
+#endif
+ BOOST_PRIVATE_INT_EXACT_BUILDER( signed char, 5 );
+ BOOST_PRIVATE_UINT_EXACT_BUILDER( unsigned char, 5 );
+
+#undef BOOST_PRIVATE_INT_EXACT_BUILDER
+#undef BOOST_PRIVATE_UINT_EXACT_BUILDER
+
// map an extreme value to a category
template < intmax_t MaxValue >
struct int_max_rank_helper
{
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (MaxValue > 0) * (
#ifdef BOOST_HAS_LONG_LONG
(MaxValue <= integer_traits< long_long_type >::const_max) +
#elif defined(BOOST_HAS_MS_INT64)
@@ -131,13 +173,13 @@ namespace detail
(MaxValue <= integer_traits< long >::const_max) +
(MaxValue <= integer_traits< int >::const_max) +
(MaxValue <= integer_traits< short >::const_max) +
- (MaxValue <= integer_traits< signed char >::const_max) );
+ (MaxValue <= integer_traits< signed char >::const_max)) );
};
template < intmax_t MinValue >
struct int_min_rank_helper
{
- BOOST_STATIC_CONSTANT( int, rank =
+ BOOST_STATIC_CONSTANT( int, rank = (MinValue < 0) * (
#ifdef BOOST_HAS_LONG_LONG
(MinValue >= integer_traits< long_long_type >::const_min) +
#elif defined(BOOST_HAS_MS_INT64)
@@ -148,7 +190,7 @@ namespace detail
(MinValue >= integer_traits< long >::const_min) +
(MinValue >= integer_traits< int >::const_min) +
(MinValue >= integer_traits< short >::const_min) +
- (MinValue >= integer_traits< signed char >::const_min) );
+ (MinValue >= integer_traits< signed char >::const_min)) );
};
template < uintmax_t Value >
@@ -168,12 +210,66 @@ namespace detail
(Value <= integer_traits< unsigned char >::const_max) );
};
+ // convert rank to type, Boost.MPL-style
+ template < int Rank, typename Signedness, class Enable = void >
+ struct integral_rank_to_type
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+ // No "signed" nor "type" here
+ };
+
+ template < int Rank >
+ struct integral_rank_to_type< Rank, signed, typename
+ enable_if_c<(lowest_integral_rank <= Rank) && (Rank <=
+ highest_integral_rank)>::type >
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+ BOOST_STATIC_CONSTANT( bool, is_signed = true );
+ typedef typename int_least_helper< Rank, signed >::least type;
+ };
+
+ template < int Rank >
+ struct integral_rank_to_type< Rank, unsigned, typename
+ enable_if_c<(lowest_integral_rank <= Rank) && (Rank <=
+ highest_integral_rank)>::type >
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = true );
+ BOOST_STATIC_CONSTANT( bool, is_signed = false );
+ typedef typename int_least_helper< Rank, unsigned >::least type;
+ };
+
} // namespace detail
+ // MPL-compatible integer-mapping class templates ------------------------//
+
+ // exact number of bits
+ template < int Bits, typename Signedness >
+ struct exact_integral
+ {
+ BOOST_STATIC_CONSTANT( bool, is_specialized = false );
+ BOOST_STATIC_CONSTANT( int, bit_count = Bits );
+ };
+
+ template < int BitsIncludingSign >
+ struct exact_integral< BitsIncludingSign, signed >
+ : detail::integral_rank_to_type<
+ detail::int_exact_rank_helper::rank, signed >
+ {
+ BOOST_STATIC_CONSTANT( int, bit_count = BitsIncludingSign );
+ };
+
+ template < int Bits >
+ struct exact_integral< Bits, unsigned >
+ : detail::integral_rank_to_type<
+ detail::uint_exact_rank_helper::rank, unsigned >
+ {
+ BOOST_STATIC_CONSTANT( int, bit_count = Bits );
+ };
+
// integer templates specifying number of bits ---------------------------//
// signed
- template< int Bits > // bits (including sign) required
+ template< int Bits > // minimum bits (including sign) required
struct int_t
{
typedef typename detail::int_least_helper
@@ -183,8 +279,14 @@ namespace detail
typedef typename int_fast_t::fast fast;
};
+ template< int Bits > // exact bits (including sign) desired
+ struct int_exact_t
+ {
+ typedef typename exact_integral::type exact;
+ };
+
// unsigned
- template< int Bits > // bits required
+ template< int Bits > // minimum bits required
struct uint_t
{
typedef typename detail::int_least_helper
@@ -195,6 +297,12 @@ namespace detail
// int_fast_t<> works correctly for unsigned too, in spite of the name.
};
+ template< int Bits > // exact bits desired
+ struct uint_exact_t
+ {
+ typedef typename exact_integral::type exact;
+ };
+
// integer templates specifying extreme value ----------------------------//
// signed
diff --git a/include/boost/integer_fwd.hpp b/include/boost/integer_fwd.hpp
index 312cd7b..01b9d2a 100644
--- a/include/boost/integer_fwd.hpp
+++ b/include/boost/integer_fwd.hpp
@@ -87,12 +87,21 @@ template < >
template < typename LeastInt >
struct int_fast_t;
+template < int Bits, typename Signedness >
+ struct exact_integral;
+
template< int Bits >
struct int_t;
+template< int Bits >
+ struct int_exact_t;
+
template< int Bits >
struct uint_t;
+template< int Bits >
+ struct uint_exact_t;
+
template< intmax_t MaxValue >
struct int_max_value_t;
diff --git a/integer.htm b/integer.htm
index 11b2f5b..0743ed4 100644
--- a/integer.htm
+++ b/integer.htm
@@ -23,6 +23,7 @@ is particularly useful for solving generic programming problems.
Synopsis
Processor-Optimized Types
Sized Types
+ MPL-Compatible Variants
Example
Demonstration Program
Rationale
@@ -32,7 +33,8 @@ is particularly useful for solving generic programming problems.
-#include <boost/integer_fwd.hpp> // forwarding header
+
+#include <boost/integer_fwd.hpp> // forwarding header
#include <boost/cstdint.hpp> // for boost::uintmax_t, intmax_t
namespace boost
@@ -52,6 +54,12 @@ namespace boost
typedef int_fast_t<least>::fast fast;
};
+ template< int Bits >
+ struct int_exact_t
+ {
+ typedef implementation_supplied exact;
+ };
+
// unsigned
template< int Bits >
struct uint_t
@@ -60,6 +68,12 @@ namespace boost
typedef int_fast_t<least>::fast fast;
};
+ template< int Bits >
+ struct uint_exact_t
+ {
+ typedef implementation_supplied exact;
+ };
+
// signed
template< intmax_t MaxValue >
struct int_max_value_t
@@ -82,6 +96,17 @@ namespace boost
typedef implementation_supplied least;
typedef int_fast_t<least>::fast fast;
};
+
+ // MPL-compatible
+ template< int Bits, typename Signedness >
+ struct exact_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;
+ };
} // namespace boost
@@ -107,65 +132,230 @@ type.
-The int_t
, uint_t
,
-int_max_value_t
, int_min_value_t
, and
-uint_value_t
class templates find the most appropiate
-built-in integral type for the given template parameter. This type is
-given by the class member least
. The easiest-to-manipulate
-version of that type is given by the class member fast
.
-The following table describes each template's criteria.
+The int_t
, int_exact_t
, uint_t
,
+uint_exact_t
, int_max_value_t
,
+int_min_value_t
, and uint_value_t
class templates find
+the most appropriate built-in integral type for the given template parameter.
+This type is given by the class member least
or exact
.
+For the non-exact class templates, the easiest-to-manipulate version of that
+type is given by the class member fast
. The following table
+describes each template's criteria.
-
+
Criteria for the Sized Type Class Templates
- Class Template |
+ Class Template (all in name-space boost ) |
Template Parameter Mapping |
- boost::int_t |
+ int_t |
The smallest built-in signed integral type with at least the
given number of bits, including the sign bit. The parameter
- should be a positive number. A compile-time error results if
+ must be a positive number. A compile-time error results if
the parameter is larger than the number of bits in a
- long . |
+ boost::intmax_t
.
- boost::uint_t |
+ int_exact_t |
+ The smallest built-in signed integral type with exactly the
+ given number of bits, including the sign bit. A compile-time error
+ results if no qualifying type exists. |
+
+
+ uint_t |
The smallest built-in unsigned integral type with at least
- the given number of bits. The parameter should be a positive
- number. A compile-time error results if the parameter is
- larger than the number of bits in an unsigned
- long . |
+ the given number of bits. The parameter must be a
+ non-negative number. A compile-time error results if the parameter
+ is larger than the number of bits in a
+ boost::uintmax_t
.
- boost::int_max_value_t |
+ uint_exact_t |
+ The smallest built-in unsigned integral type with exactly the given
+ number of bits. A compile-time error results if no qualifying type
+ exists. |
+
+
+ int_max_value_t |
The smallest built-in signed integral type that supports the
- given value as a maximum. The parameter should be a
+ given value as a maximum. The parameter must be a
positive number. |
- boost::int_min_value_t |
+ int_min_value_t |
The smallest built-in signed integral type that supports the
- given value as a minimum. The parameter should be a
+ given value as a minimum. The parameter must be a
negative number. |
- boost::uint_value_t |
+ uint_value_t |
The smallest built-in unsigned integral type that supports
the given value as a maximum. The parameter should be a
positive number. |
+
+
+The bit-length sized-type class templates have several drawbacks:
+
+
+ - You must know the valid bit-lengths in advance.
+ - There is no way to inspect the parameter used after a size-type template
+ class is aliased.
+ - Using an inappropriate parameter value results in a compiler
+ diagnostic.
+ - The type names used are inconsistent with other transformations in
+ Boost, like in MPL.
+ - The above two facts make use of the size-type class templates
+ incompatible with template meta-programming techniques.
+
+
+The exact_integral
class template provides an MPL-compatible
+alternative. This alternative has the form:
+
+
+template< SwitchType SwitchValue, typename Signedness >
+struct name
+{
+ static bool const is_specialized = implementation_supplied;
+ static bool const is_signed = implementation_supplied;
+ static SwitchType const switch_id = SwitchValue;
+
+ typedef implementation_supplied type;
+};
+
+
+Each member, if present, is defined by:
+
+
+ Members in MPL-Compatible Class Templates
+
+ Class Template Member |
+ When Defined |
+ Meaning |
+
+
+ is_specialized |
+ Always |
+ Flag indicating when a particular template class instantiation is a
+ valid meta-function (true ) or not (false ). |
+
+
+ is_signed |
+ is_specialized == true |
+ Flag indicating whether the signed-variant (true ) or
+ the unsigned-variant (false ) of the meta-function is
+ used. This is controlled by the Signedness template
+ parameter:
+
+ Effect of Signedness Setting
+
+ Signedness Type |
+ is_signed |
+
+
+ signed |
+ true |
+
+
+ unsigned |
+ false |
+
+
+ anything else |
+ not defined |
+
+
+ The type used is a programmer mnemonic; the compiler cannot prevent
+ someone from using int or signed int
+ instead of signed , or unsigned int instead
+ of unsigned . |
+
+
+ switch_id (Actual name is template-specific.) |
+ Always |
+ The value of the main control parameter, accessible even if the
+ template class instantiation is aliased. |
+
+
+ type |
+ is_specialized == true |
+ The meta-function's result. It appears only if the input parameters
+ satisfy the template's requirements. It's presence, or lack thereof,
+ enables "Substitution Failure Is Not An Error" (SFINAE)
+ techniques, instead of a hard compiler diagnostic. |
+
+
+
+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
+controls the appropriate emulation.)
+
+
+ Criteria for the MPL-Compatible Class Templates
+
+ Class Template (all in name-space boost ) |
+ Parameter Type |
+ Parameter Member ID |
+ Classic Equivalent |
+ Template Parameter Mapping (when type is defined) |
+
+
+ Signed |
+ Unsigned |
+
+
+ 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. |
+
+
+
-#include <boost/integer.hpp>
+
+#include <boost/integer.hpp>
+#include <boost/mpl/int.hpp>
+#include <iostream>
+#include <ostream>
+
+//...
+
+template < int Bits >
+bool
+fit_exactly( boost::mpl::int_<Bits> const &x,
+ typename boost::exact_integral<Bits, signed>::type *unused = 0 )
+{
+ return true;
+}
+
+template < typename T >
+bool
+fit_exactly( T const &x )
+{
+ return false;
+}
//...
int main()
{
- boost::int_t<24>::least my_var;
+ typedef boost::mpl::int_<24> twenty_four;
+
+ boost::int_t<twenty_four::value>::least my_var;
+
+ //...
+
+ std::cout << "my_var " << ( fit_exactly(twenty_four()) ? "does" :
+ "does not" ) << " fit its type exactly." << std::endl;
+
//...
}
@@ -201,11 +391,11 @@ to Valentin Bonnard and
Kevlin Henney for sharing
their designs for similar templates. Daryle Walker designed the
-value-based sized templates.
+exact and value-based sized templates, and the MPL-compatible templates.
-Revised July 14, 2008
+Revised July 15, 2008
© Copyright Beman Dawes 1999. Use, modification, and distribution are
subject to the Boost Software License, Version 1.0. (See accompanying file // unit testing framework
-#include // ..BOOST_AUTO_TEST_CASE_TEMPLATE
+#include
#include // for BOOST_NO_USING_TEMPLATE, etc.
#include // for boost::uintmax_t, intmax_t
@@ -47,10 +48,12 @@
#include // for boost::is_same
#include // for boost::make_signed
-#include // for ULONG_MAX, LONG_MAX, LONG_MIN, etc.
-#include // for std::cout
-#include // for std::endl
-#include // for std::type_info
+#include // for std::binary_search
+#include // for ULONG_MAX, LONG_MAX, LONG_MIN, etc.
+#include // for std::size_t
+#include // for std::cout
+#include // for std::endl
+#include // for std::type_info
// Control what the "fast" specialization of "short" is
@@ -104,9 +107,9 @@ typedef boost::mpl::vector<
#if ULONG_MAX > UINT_MAX
, unsigned long
#endif
-#ifdef BOOST_HAS_LONG_LONG
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
, boost::ulong_long_type
-#elif defined(BOOST_HAS_MS_INT64)
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
, unsigned __int64
#endif
> distinct_unsigned_types;
@@ -188,9 +191,77 @@ typedef boost::mpl::push_back<
// mantissa (don't want to shift into the sign bit)
typedef boost::mpl::push_back<
boost::mpl::pop_back< valid_bits_list >::type,
- boost::mpl::integral_c< int, intmax_bits - 2 >
+ boost::mpl::integral_c< int, intmax_bits - 3 >
>::type valid_to_increase_sbits_list;
+// List the digit counts for each integral type, this time as an object, an
+// array working as a sorted list
+int const integral_bit_lengths[] = {
+ std::numeric_limits< unsigned char >::digits
+#if USHRT_MAX > UCHAR_MAX
+ , std::numeric_limits< unsigned short >::digits
+#endif
+#if UINT_MAX > USHRT_MAX
+ , std::numeric_limits< unsigned int >::digits
+#endif
+#if ULONG_MAX > UINT_MAX
+ , std::numeric_limits< unsigned long >::digits
+#endif
+#if defined(BOOST_HAS_LONG_LONG) && ((ULLONG_MAX > ULONG_MAX) || (ULONGLONG_MAX > ULONG_MAX))
+ , std::numeric_limits< boost::ulong_long_type >::digits
+#elif defined(BOOST_HAS_MS_INT64) && (0xFFFFFFFFFFFFFFFFui64 > ULONG_MAX)
+ , std::numeric_limits< unsigned __int64 >::digits
+#endif
+};
+
+std::size_t const integral_type_count = sizeof(integral_bit_lengths) /
+ sizeof(integral_bit_lengths[0]);
+
+// 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 )
+{
+ // 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 an exact_integral<" << bits <<
+ ", signed> specialization, with type '" << typeid(typename
+ boost::exact_integral::type).name() << "'." );
+ return true;
+}
+
+template < typename T >
+bool
+print_out_exact_signed( T const &x, int bits )
+{
+ PRIVATE_SHOW_MESSAGE( "There is no exact_integral<" << bits <<
+ ", signed> specialization." );
+ return false;
+}
+
+template < int Bits >
+bool
+print_out_exact_unsigned( boost::mpl::integral_c const &x, int bits,
+ typename boost::exact_integral::type *unused = 0 )
+{
+ PRIVATE_SHOW_MESSAGE( "There is an exact_integral<" << bits <<
+ ", unsigned> specialization, with type '" << typeid(typename
+ boost::exact_integral::type).name() << "'." );
+ return true;
+}
+
+template < typename T >
+bool
+print_out_exact_unsigned( T const &x, int bits )
+{
+ PRIVATE_SHOW_MESSAGE( "There is no exact_integral<" << bits <<
+ ", unsigned> specialization." );
+ return false;
+}
+
} // unnamed namespace
@@ -225,7 +296,7 @@ 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
+// 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 )
{
// This test is supposed to replace the following printouts given in
@@ -348,6 +419,42 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_shifted_signed_values_test, T,
typename int_t::least>::value) );
}
+// Check the specialization type status of given bit lengths, exact only
+BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_exact_lengths_test, T, bits_list )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using std::binary_search;
+#else
+ using namespace std;
+#endif
+
+ BOOST_CHECK_EQUAL( print_out_exact_signed(T(), T::value),
+ binary_search(integral_bit_lengths, integral_bit_lengths +
+ integral_type_count, T::value) );
+ BOOST_CHECK_EQUAL( print_out_exact_unsigned(T(), T::value),
+ binary_search(integral_bit_lengths, integral_bit_lengths +
+ integral_type_count, T::value) );
+}
+
+// Check the classic specialization type status of given bit lengths, exact only
+BOOST_AUTO_TEST_CASE_TEMPLATE( show_types_for_classic_exact_lengths_test, T,
+ distinct_integral_bit_counts )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using std::numeric_limits;
+ using boost::int_exact_t;
+ using boost::uint_exact_t;
+#else
+ using namespace std;
+ using namespace boost;
+#endif
+
+ BOOST_MPL_ASSERT_RELATION( numeric_limits::exact>::digits, ==, T::value - 1 );
+ BOOST_MPL_ASSERT_RELATION( numeric_limits::exact>::digits, ==, T::value );
+}
+
BOOST_AUTO_TEST_SUITE_END()
// Check if given constants can fit in given types
@@ -398,8 +505,36 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_masked_values_test, T,
1 );
}
-// Check if large value can fit its minimum required size, by value
-BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T,
+// Check if a large value can only fit of its exact bit length
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_exact_lengths_test, T,
+ distinct_integral_bit_counts )
+{
+#ifndef BOOST_NO_USING_TEMPLATE
+ using boost::exact_integral;
+#else
+ using namespace boost;
+#endif
+
+ typedef typename exact_integral::type uexact_type;
+ typedef typename exact_integral::type sexact_type;
+
+ uexact_type const one_u( 1u ), high_bit_u( one_u << (T::value - 1) ),
+ repeated_bits_u( (high_bit_u << 1) | high_bit_u );
+
+ BOOST_CHECK( high_bit_u );
+ BOOST_CHECK_EQUAL( repeated_bits_u, high_bit_u );
+
+ sexact_type const one_s( 1 ), high_bit_s( one_s << (T::value - 2) ),
+ repeated_bits_s( (high_bit_s << 1) | high_bit_s ),
+ repeated_2bits_s( (repeated_bits_s << 1) | high_bit_s );
+
+ BOOST_CHECK( high_bit_s > 0 );
+ BOOST_CHECK( repeated_bits_s < 0 );
+ BOOST_CHECK_EQUAL( repeated_bits_s, repeated_2bits_s );
+}
+
+// Check if large value can fit its minimum required size, by value, unsigned
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_unsigned_values_test, T,
valid_to_increase_ubits_list )
{
// This test is supposed to replace the following checks given in
@@ -409,28 +544,21 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T,
// Confirm( static_cast::Type>(V) == V );
// end for
// end Routine
- // with Template = {uint_value_t, int_max_value_t, int_min_value_t}; Type =
- // {least, fast}; Template:Extreme = {intmax_t.Min for int_min_value_t,
- // intmax_t.Max for int_max_value_t, uintmax_t.Max for uint_value_t}
+ // with Template = {uint_value_t}; Type = {least, fast}; Template:Extreme =
+ // {uintmax_t.Max for uint_value_t}
// In other words, the selected type doesn't mask out any bits it's not
// supposed to. But now we'll use template meta-programming instead of
// macros. The limit of type-lists is usually less than 32 (not to mention
// 64) elements, so we have to take selected values.
using boost::uintmax_t;
- using boost::intmax_t;
#ifndef BOOST_NO_USING_TEMPLATE
- using boost::integer_traits;
using boost::uint_value_t;
- using boost::int_max_value_t;
- using boost::int_min_value_t;
#else
using namespace boost;
#endif
- int const shift = T::value;
- uintmax_t const max_u = integer_traits::const_max >> shift;
- intmax_t const max_s = integer_traits::const_max >> shift,
- min_s = integer_traits::const_min >> shift;
+ uintmax_t const max_u = boost::integer_traits::const_max >>
+ T::value;
BOOST_CHECK_EQUAL( typename uint_value_t::least(max_u), max_u );
BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::least(max_u >> 1),
@@ -438,6 +566,38 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_values_test, T,
BOOST_CHECK_EQUAL( typename uint_value_t::fast(max_u), max_u );
BOOST_CHECK_EQUAL( typename uint_value_t<(max_u >> 1)>::fast(max_u >> 1),
max_u >> 1 );
+}
+
+// Check if large value can fit its minimum required size, by value, signed
+BOOST_AUTO_TEST_CASE_TEMPLATE( fit_for_shifted_signed_values_test, T,
+ valid_to_increase_sbits_list )
+{
+ // This test is supposed to replace the following checks given in
+ // puesdo-code by:
+ // Routine: Template, Type
+ // for ( N = 0, V = Template:Extreme ; N < 32 ; ++N, V >>= 1 )
+ // Confirm( static_cast::Type>(V) == V );
+ // end for
+ // end Routine
+ // with Template = {int_max_value_t, int_min_value_t}; Type = {least, fast};
+ // Template:Extreme = {intmax_t.Min for int_min_value_t, intmax_t.Max
+ // for int_max_value_t}
+ // In other words, the selected type doesn't mask out any bits it's not
+ // supposed to. But now we'll use template meta-programming instead of
+ // macros. The limit of type-lists is usually less than 32 (not to mention
+ // 64) elements, so we have to take selected values.
+ using boost::intmax_t;
+#ifndef BOOST_NO_USING_TEMPLATE
+ using boost::integer_traits;
+ using boost::int_max_value_t;
+ using boost::int_min_value_t;
+#else
+ using namespace boost;
+#endif
+
+ int const shift = T::value;
+ intmax_t const max_s = integer_traits::const_max >> shift,
+ min_s = integer_traits::const_min >> shift;
BOOST_CHECK_EQUAL( typename int_max_value_t::least(max_s), max_s );
BOOST_CHECK_EQUAL( typename int_max_value_t<(max_s >> 1)>::least(max_s >>