forked from boostorg/integer
Added MPL-compatible variants of the integer-mask class templates (and finally make the lowest-bit-group metafunctions work for zero-length bit-groups)
[SVN r47869]
This commit is contained in:
@ -8,7 +8,11 @@
|
||||
<h1><img src="../../../boost.png" alt="boost.png (6897 bytes)"
|
||||
align="middle" width="277" height="86">Integer Bit Mask Templates</h1>
|
||||
|
||||
<p>The class templates in <cite><a href="../../../boost/integer/integer_mask.hpp"><boost/integer/integer_mask.hpp></a></cite> provide bit masks for a certain bit position or a contiguous-bit pack of a certain size. The types of the masking constants come from the <a href="../integer.htm">integer type selection templates</a> header.</p>
|
||||
<p>The class templates in <cite><a
|
||||
href="../../../boost/integer/integer_mask.hpp"><boost/integer/integer_mask.hpp></a></cite>
|
||||
provide bit masks for a certain bit position or a contiguous-bit pack of a
|
||||
certain size. The types of the masking constants come from the <a
|
||||
href="../integer.htm">integer type selection templates</a> header.</p>
|
||||
|
||||
<h2><a name="contents">Contents</a></h2>
|
||||
|
||||
@ -17,6 +21,7 @@ align="middle" width="277" height="86">Integer Bit Mask Templates</h1>
|
||||
<li><a href="#synopsis">Synopsis</a></li>
|
||||
<li><a href="#single">Single Bit-Mask Class Template</a></li>
|
||||
<li><a href="#group">Group Bit-Mask Class Template</a></li>
|
||||
<li><a href="#mpl">MPL-Compatible Variants</a></li>
|
||||
<li><a href="#example">Example</a></li>
|
||||
<li><a href="#demo">Demonstration Program</a></li>
|
||||
<li><a href="#rationale">Rationale</a></li>
|
||||
@ -26,39 +31,68 @@ align="middle" width="277" height="86">Integer Bit Mask Templates</h1>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <<a href="../../../boost/integer_fwd.hpp">boost/integer_fwd.hpp</a>> <i>// forwarding header</i>
|
||||
#include <<a href="../../../boost/integer.hpp">boost/integer.hpp</a>> <i>// for boost::int_fast_t</i>
|
||||
#include <cstddef> <i>// for std::size_t</i>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template < std::size_t Bit >
|
||||
struct high_bit_mask_t
|
||||
// MPL-compatible
|
||||
template < int Offset >
|
||||
struct integer_hi_mask
|
||||
{
|
||||
typedef <em>implementation_supplied</em> least;
|
||||
typedef <em>implementation_supplied</em> fast;
|
||||
static bool const is_specialized = <em>implementation_supplied</em>;
|
||||
static int const bit_offset = Offset;
|
||||
|
||||
static const least high_bit = <em>implementation_defined</em>;
|
||||
static const fast high_bit_fast = <em>implementation_defined</em>;
|
||||
typedef <em>implementation_supplied</em> type;
|
||||
typedef <em>implementation_supplied</em> value_type;
|
||||
static value_type const value = <em>implementation_supplied</em>;
|
||||
// There are other (optional) operations....
|
||||
};
|
||||
|
||||
template < int Length >
|
||||
struct integer_lo_mask
|
||||
{
|
||||
static bool const is_specialized = <em>implementation_supplied</em>;
|
||||
static int const bit_count = Length;
|
||||
|
||||
typedef <em>implementation_supplied</em> type;
|
||||
typedef <em>implementation_supplied</em> value_type;
|
||||
static value_type const value = <em>implementation_supplied</em>;
|
||||
// There are other (optional) operations....
|
||||
};
|
||||
|
||||
// single
|
||||
template < std::size_t Bit >
|
||||
class high_bit_mask_t
|
||||
{
|
||||
public:
|
||||
typedef typename integer_hi_mask<Bit>::value_type least;
|
||||
typedef int_fast_t<least>::fast fast;
|
||||
|
||||
static const least high_bit = integer_hi_mask<Bit>::value;
|
||||
static const fast high_bit_fast = high_bit;
|
||||
|
||||
static const std::size_t bit_position = Bit;
|
||||
|
||||
};
|
||||
|
||||
// group
|
||||
template < std::size_t Bits >
|
||||
struct low_bits_mask_t
|
||||
class low_bits_mask_t
|
||||
{
|
||||
typedef <em>implementation_supplied</em> least;
|
||||
typedef <em>implementation_supplied</em> fast;
|
||||
public:
|
||||
typedef typename integer_lo_mask<Bits>::value_type least;
|
||||
typedef int_fast_t<least>::fast fast;
|
||||
|
||||
static const least sig_bits = <em>implementation_defined</em>;
|
||||
static const fast sig_bits_fast = <em>implementation_defined</em>;
|
||||
static const least sig_bits = integer_lo_mask<Bits>::value;
|
||||
static const fast sig_bits_fast = sig_bits;
|
||||
|
||||
static const std::size_t bit_count = Bits;
|
||||
|
||||
};
|
||||
|
||||
// Specializations for low_bits_mask_t exist for certain bit counts.
|
||||
|
||||
} // namespace boost
|
||||
</pre></blockquote>
|
||||
|
||||
@ -149,16 +183,149 @@ describes the members of an instantiation of
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><strong>Implementation Note</strong><br>
|
||||
When <code>Bits</code> is the exact size of a built-in unsigned type,
|
||||
the implementation has to change to prevent undefined behavior.
|
||||
Therefore, there are specializations of <code>low_bits_mask_t</code> at
|
||||
those bit counts.</p>
|
||||
<h2><a name="mpl">MPL-Compatible Variants</a></h2>
|
||||
|
||||
<p>The single and group bit-mask class templates have several drawbacks:</p>
|
||||
|
||||
<ul>
|
||||
<li>You must know the valid bit-lengths in advance.</li>
|
||||
<li>Using an inappropriate parameter value results in a compiler
|
||||
diagnostic.</li>
|
||||
<li>The type names used are inconsistent with other transformations in
|
||||
Boost, like in <a href="../../mpl/">MPL</a>.</li>
|
||||
<li>The above two facts make use of the regular bit-mask class templates
|
||||
incompatible with template meta-programming techniques.</li>
|
||||
</ul>
|
||||
|
||||
<p>The <code>integer_hi_mask</code> and <code>integer_lo_mask</code> class
|
||||
templates provide MPL-compatible alternatives. These alternatives have the
|
||||
form:</p>
|
||||
|
||||
<blockquote><pre>
|
||||
template< int <var>Size</var> >
|
||||
struct <var>name</var>
|
||||
{
|
||||
static bool const is_specialized = <em>implementation_supplied</em>;
|
||||
static int const <var>switch_id</var> = <var>Size</var>;
|
||||
|
||||
typedef <em>implementation_supplied</em> type;
|
||||
typedef <em>implementation_supplied</em> value_type;
|
||||
static value_type const value = <em>implementation_supplied</em>;
|
||||
// with other operations...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Only some of the members are always present. The presence of other members
|
||||
and operations is flagged by the (always-present) <code>is_specialized</code>.</p>
|
||||
|
||||
<table border="2" cellpadding="5" align="center">
|
||||
<caption>Permanent Members of the MPL-Compatible Masking Class Template
|
||||
Types</caption>
|
||||
<tr>
|
||||
<th>Class Template Member</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>is_specialized</code></td>
|
||||
<td>Flag indicating when a particular template class instantiation is a
|
||||
valid meta-function (<code>true</code>) or not (<code>false</code>).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><var>switch_id</var></code> (Actual name is template-specific.)</td>
|
||||
<td>The value of the main control parameter, accessible even if the
|
||||
template class instantiation is aliased.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The optional members are based from inheriting from a <a
|
||||
href="../../mpl/doc/refmanual/integral-constant.html">MPL-style Integral
|
||||
Constant</a> type, but only if <code>is_specialized</code> is <code>true</code>.</p>
|
||||
|
||||
<table border="2" cellpadding="5" align="center">
|
||||
<caption>Optional Members of the MPL-Compatible Masking Types</caption>
|
||||
<tr>
|
||||
<th>Class Template Member</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>value</code></td>
|
||||
<td>The actual bit mask.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>value_type</code></td>
|
||||
<td>The type of the bit mask value.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>type</code></td>
|
||||
<td>The Integral Constant</a> implementation type, which should be
|
||||
<code><a href="../../mpl/doc/refmanual/integral-c.html">boost::mpl::
|
||||
integral_c</a>< <var>value_type</var>, <var>value</var>
|
||||
></code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The Integral Constant prototype also adds the following operations:</p>
|
||||
|
||||
<table border="2" cellpadding="5" align="center">
|
||||
<caption>Optional Operations of the MPL-Compatible Masking Types</caption>
|
||||
<tr>
|
||||
<th>Operation (with <var>n</var> as a masking type)</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>boost::mpl::next< n >::type</code></td>
|
||||
<td><code>boost::mpl::next< n::type >::type</code>, i.e.
|
||||
<code>boost::mpl::integral_c< n::value_type, n::value + 1
|
||||
></code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>boost::mpl::prior< n >::type</code></td>
|
||||
<td><code>boost::mpl::prior< n::type >::type</code>, i.e.
|
||||
<code>boost::mpl::integral_c< n::value_type, n::value - 1
|
||||
></code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>n::value_type const c = n();</code></td>
|
||||
<td><var>c</var> is set to <code>n::value</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The specifics for each masking class template are:</p>
|
||||
|
||||
<table border="2" cellpadding="5" align="center">
|
||||
<caption>Criteria for the MPL-Compatible Masking Types<br>
|
||||
(Everything besides the parameter ID is in name-space
|
||||
<code>boost</code> except where indicated.)</caption>
|
||||
<tr>
|
||||
<th>Class Template</th>
|
||||
<th>Parameter Member ID</th>
|
||||
<th>Classic Equivalent</th>
|
||||
<th>Value Type</th>
|
||||
<th>Value</th>
|
||||
<th>Valid Range</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>integer_hi_mask</code></td>
|
||||
<td><code>bit_offset</code></td>
|
||||
<td><code>high_bit_mask_t</code></td>
|
||||
<td><code>sized_integral < bit_offset + 1, unsigned ></code></td>
|
||||
<td>2<sup><code>bit_offset</code></sup></td>
|
||||
<td><code>0 <= bit_offset < std::numeric_limits< uintmax_t >::digits</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>integer_lo_mask</code></td>
|
||||
<td><code>bit_count</code></td>
|
||||
<td><code>low_bits_mask_t</code></td>
|
||||
<td><code>sized_integral < bit_count, unsigned ></code></td>
|
||||
<td>2<sup><code>bit_offset</code></sup> - 1</td>
|
||||
<td><code>0 <= bit_count <= std::numeric_limits< uintmax_t >::digits</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
|
||||
<blockquote><pre>
|
||||
#include <boost/integer/integer_mask.hpp>
|
||||
#include <<a href="../../../boost/integer/integer_mask.hpp">boost/integer/integer_mask.hpp</a>>
|
||||
|
||||
//...
|
||||
|
||||
@ -200,7 +367,7 @@ href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised September 23, 2001</p>
|
||||
<p>Revised July 29, 2008</p>
|
||||
|
||||
<p>© Copyright Daryle Walker 2001. Use, modification, and distribution are
|
||||
subject to the Boost Software License, Version 1.0. (See accompanying file <a
|
||||
|
@ -13,86 +13,191 @@
|
||||
#include <boost/integer_fwd.hpp> // self include
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
|
||||
#include <boost/integer.hpp> // for boost::uint_t
|
||||
|
||||
#include <boost/detail/extended_integer.hpp> // for BOOST_HAS_XINT, etc.
|
||||
|
||||
#include <climits> // for UCHAR_MAX, etc.
|
||||
#include <cstddef> // for std::size_t
|
||||
|
||||
#include <boost/cstdint.hpp> // for boost::uintmax_t
|
||||
#include <boost/integer.hpp> // for boost::sized_integral
|
||||
#include <boost/limits.hpp> // for std::numeric_limits
|
||||
#include <boost/mpl/and.hpp> // for boost::mpl::and_
|
||||
#include <boost/mpl/bitwise.hpp> // for boost::mpl::bitor_, shift_left
|
||||
#include <boost/mpl/bool.hpp> // for boost::mpl::true_
|
||||
#include <boost/mpl/comparison.hpp> // for boost::mpl::greater_equal, etc.
|
||||
#include <boost/mpl/empty_base.hpp> // for boost::mpl::empty_base
|
||||
#include <boost/mpl/if.hpp> // for boost::mpl::if_
|
||||
#include <boost/mpl/int.hpp> // for boost::mpl::int_
|
||||
#include <boost/mpl/integral_c.hpp> // for boost::integral_c
|
||||
#include <boost/mpl/next_prior.hpp> // for boost::mpl::next, prior
|
||||
#include <boost/utility/enable_if.hpp> // for boost::enable_if
|
||||
|
||||
#include <cstddef> // for std::size_t
|
||||
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Helper templates --------------------------------------------------------//
|
||||
|
||||
template < int Bits >
|
||||
struct hi_integer_mask_builder1
|
||||
{
|
||||
typedef boost::mpl::int_<Bits> bit_count_type;
|
||||
|
||||
typedef typename boost::mpl::next<bit_count_type>::type
|
||||
mask_length_type;
|
||||
typedef boost::sized_integral<mask_length_type::value, unsigned>
|
||||
mask_type;
|
||||
|
||||
typedef boost::mpl::integral_c<typename mask_type::type, 1> one_type;
|
||||
typedef boost::mpl::shift_left<one_type, bit_count_type> result_type;
|
||||
};
|
||||
|
||||
template < int Bits >
|
||||
struct hi_integer_mask_builder2
|
||||
{
|
||||
typedef boost::mpl::int_<Bits> bit_count_type;
|
||||
|
||||
typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> >
|
||||
lo_bound_type;
|
||||
typedef boost::mpl::less< bit_count_type,
|
||||
boost::mpl::int_<std::numeric_limits<boost::uintmax_t>::digits> >
|
||||
hi_bound_type;
|
||||
typedef boost::mpl::and_<lo_bound_type, hi_bound_type> count_valid_type;
|
||||
};
|
||||
|
||||
template < int Bits, class Enable = void >
|
||||
struct hi_integer_mask_builder3
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( bool, is_specialized = false );
|
||||
};
|
||||
|
||||
template < int Bits >
|
||||
struct hi_integer_mask_builder3< Bits, typename boost::enable_if<typename
|
||||
hi_integer_mask_builder2<Bits>::count_valid_type>::type >
|
||||
: hi_integer_mask_builder1<Bits>::result_type
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( bool, is_specialized = true );
|
||||
};
|
||||
|
||||
template < int Bits >
|
||||
struct lo_integer_mask_builder1
|
||||
{
|
||||
typedef boost::mpl::int_<Bits> bit_count_type;
|
||||
|
||||
typedef typename boost::mpl::prior<bit_count_type>::type
|
||||
shift_length_type;
|
||||
typedef boost::sized_integral<bit_count_type::value, unsigned>
|
||||
mask_type;
|
||||
|
||||
typedef boost::mpl::integral_c<typename mask_type::type, 1> one_type;
|
||||
typedef boost::mpl::shift_left<one_type, shift_length_type>
|
||||
high_bit_type;
|
||||
typedef typename boost::mpl::prior<high_bit_type>::type low_bits_type;
|
||||
typedef boost::mpl::bitor_<high_bit_type, low_bits_type> result_type;
|
||||
};
|
||||
|
||||
template < >
|
||||
struct lo_integer_mask_builder1< 0 >
|
||||
{
|
||||
// Let's not deal with negative interim values....
|
||||
typedef boost::mpl::integral_c<unsigned char, 0u> result_type;
|
||||
};
|
||||
|
||||
template < int Bits >
|
||||
struct lo_integer_mask_builder2
|
||||
{
|
||||
typedef boost::mpl::int_<Bits> bit_count_type;
|
||||
|
||||
typedef boost::mpl::greater_equal< bit_count_type, boost::mpl::int_<0> >
|
||||
lo_bound_type;
|
||||
typedef boost::mpl::less_equal< bit_count_type,
|
||||
boost::mpl::int_<std::numeric_limits<boost::uintmax_t>::digits> >
|
||||
hi_bound_type;
|
||||
typedef boost::mpl::and_<lo_bound_type, hi_bound_type> count_valid_type;
|
||||
};
|
||||
|
||||
template < >
|
||||
struct lo_integer_mask_builder2< 0 >
|
||||
{
|
||||
typedef boost::mpl::true_ count_valid_type;
|
||||
};
|
||||
|
||||
template < int Bits, class Enable = void >
|
||||
struct lo_integer_mask_builder3
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( bool, is_specialized = false );
|
||||
// No MPL Integral Constant to inherit from
|
||||
};
|
||||
|
||||
template < int Bits >
|
||||
struct lo_integer_mask_builder3< Bits, typename enable_if<typename
|
||||
lo_integer_mask_builder2<Bits>::count_valid_type>::type >
|
||||
: lo_integer_mask_builder1<Bits>::result_type
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( bool, is_specialized = true );
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
// MPL-compatible integer mask class templates -----------------------------//
|
||||
|
||||
// Displaced single-bit mask, 1 << Offset, 0 <= Offset < BitLengthOf(uintmax_t)
|
||||
template < int Offset >
|
||||
struct integer_hi_mask
|
||||
: detail::hi_integer_mask_builder3<Offset>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( int, bit_offset = Offset );
|
||||
};
|
||||
|
||||
// Lowest bit-group mask, 2**Length - 1, 0 <= Length <= BitLengthOf(uintmax_t)
|
||||
template < int Length >
|
||||
struct integer_lo_mask
|
||||
: detail::lo_integer_mask_builder3<Length>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( int, bit_count = Length );
|
||||
};
|
||||
|
||||
|
||||
// Specified single-bit mask class declaration -----------------------------//
|
||||
// (Lowest bit starts counting at 0.)
|
||||
|
||||
template < std::size_t Bit >
|
||||
struct high_bit_mask_t
|
||||
class high_bit_mask_t
|
||||
{
|
||||
typedef typename uint_t<(Bit + 1)>::least least;
|
||||
typedef typename uint_t<(Bit + 1)>::fast fast;
|
||||
typedef integer_hi_mask<Bit> impl_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << Bit) );
|
||||
BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << Bit) );
|
||||
public:
|
||||
typedef typename impl_type::value_type least;
|
||||
typedef typename int_fast_t<least>::fast fast;
|
||||
|
||||
BOOST_STATIC_CONSTANT( std::size_t, bit_position = Bit );
|
||||
BOOST_STATIC_CONSTANT( least, high_bit = impl_type::value );
|
||||
BOOST_STATIC_CONSTANT( fast, high_bit_fast = impl_type::value );
|
||||
|
||||
BOOST_STATIC_CONSTANT( std::size_t, bit_position = impl_type::bit_offset );
|
||||
|
||||
}; // boost::high_bit_mask_t
|
||||
|
||||
|
||||
// Specified bit-block mask class declaration ------------------------------//
|
||||
// Makes masks for the lowest N bits
|
||||
// (Specializations are needed when N fills up a type.)
|
||||
|
||||
template < std::size_t Bits >
|
||||
struct low_bits_mask_t
|
||||
class low_bits_mask_t
|
||||
{
|
||||
typedef typename uint_t<Bits>::least least;
|
||||
typedef typename uint_t<Bits>::fast fast;
|
||||
typedef integer_lo_mask<Bits> impl_type;
|
||||
|
||||
BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) );
|
||||
BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) );
|
||||
public:
|
||||
typedef typename impl_type::value_type least;
|
||||
typedef typename int_fast_t<least>::fast fast;
|
||||
|
||||
BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits );
|
||||
BOOST_STATIC_CONSTANT( least, sig_bits = impl_type::value );
|
||||
BOOST_STATIC_CONSTANT( fast, sig_bits_fast = impl_type::value );
|
||||
|
||||
BOOST_STATIC_CONSTANT( std::size_t, bit_count = impl_type::bit_count );
|
||||
|
||||
}; // boost::low_bits_mask_t
|
||||
|
||||
|
||||
#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \
|
||||
template < > struct low_bits_mask_t< std::numeric_limits<Type>::digits > { \
|
||||
typedef std::numeric_limits<Type> limits_type; \
|
||||
typedef uint_t<limits_type::digits>::least least; \
|
||||
typedef uint_t<limits_type::digits>::fast fast; \
|
||||
BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); \
|
||||
BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); \
|
||||
BOOST_STATIC_CONSTANT( std::size_t, bit_count = limits_type::digits ); \
|
||||
}
|
||||
|
||||
BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned char );
|
||||
|
||||
#if USHRT_MAX > UCHAR_MAX
|
||||
BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned short );
|
||||
#endif
|
||||
|
||||
#if UINT_MAX > USHRT_MAX
|
||||
BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int );
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX > UINT_MAX
|
||||
BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long );
|
||||
#endif
|
||||
|
||||
#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX)
|
||||
BOOST_LOW_BITS_MASK_SPECIALIZE( ::boost::detail::uxint_t );
|
||||
#endif
|
||||
|
||||
#undef BOOST_LOW_BITS_MASK_SPECIALIZE
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
@ -9,12 +9,10 @@
|
||||
#ifndef BOOST_INTEGER_FWD_HPP
|
||||
#define BOOST_INTEGER_FWD_HPP
|
||||
|
||||
#include <climits> // for UCHAR_MAX, etc.
|
||||
#include <cstddef> // for std::size_t
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_NO_INTRINSIC_WCHAR_T
|
||||
#include <boost/config.hpp> // for BOOST_NO_INTRINSIC_WCHAR_T, etc.
|
||||
#include <boost/cstdint.hpp> // for boost::uintmax_t, intmax_t
|
||||
#include <boost/limits.hpp> // for std::numeric_limits
|
||||
|
||||
#include <boost/detail/extended_integer.hpp> // for BOOST_HAS_XINT, etc.
|
||||
|
||||
@ -131,35 +129,17 @@ template< uintmax_t Value >
|
||||
|
||||
// From <boost/integer/integer_mask.hpp> -----------------------------------//
|
||||
|
||||
template < int Offset >
|
||||
struct integer_hi_mask;
|
||||
|
||||
template < int Length >
|
||||
struct integer_lo_mask;
|
||||
|
||||
template < std::size_t Bit >
|
||||
struct high_bit_mask_t;
|
||||
class high_bit_mask_t;
|
||||
|
||||
template < std::size_t Bits >
|
||||
struct low_bits_mask_t;
|
||||
|
||||
template < >
|
||||
struct low_bits_mask_t< ::std::numeric_limits<unsigned char>::digits >;
|
||||
|
||||
#if USHRT_MAX > UCHAR_MAX
|
||||
template < >
|
||||
struct low_bits_mask_t< ::std::numeric_limits<unsigned short>::digits >;
|
||||
#endif
|
||||
|
||||
#if UINT_MAX > USHRT_MAX
|
||||
template < >
|
||||
struct low_bits_mask_t< ::std::numeric_limits<unsigned int>::digits >;
|
||||
#endif
|
||||
|
||||
#if ULONG_MAX > UINT_MAX
|
||||
template < >
|
||||
struct low_bits_mask_t< ::std::numeric_limits<unsigned long>::digits >;
|
||||
#endif
|
||||
|
||||
#if BOOST_HAS_XINT && (BOOST_UXINT_MAX > ULONG_MAX)
|
||||
template < >
|
||||
struct low_bits_mask_t< ::std::numeric_limits< ::boost::detail::uxint_t
|
||||
>::digits >;
|
||||
#endif
|
||||
class low_bits_mask_t;
|
||||
|
||||
|
||||
// From <boost/integer/static_log2.hpp> ------------------------------------//
|
||||
|
@ -8,6 +8,8 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 29 Jul 2008 Added MPL-compatible variants of the integer-mask templates.
|
||||
// (Daryle Walker)
|
||||
// 27 Jul 2008 Changed tests to use the unit-test system; added
|
||||
// extended-integer support. (Daryle Walker)
|
||||
// 23 Sep 2001 Initial version (Daryle Walker)
|
||||
@ -18,24 +20,72 @@
|
||||
#include <boost/cstdint.hpp> // for boost::uintmax_t
|
||||
#include <boost/integer/integer_mask.hpp> // for boost::high_bit_mask_t, etc.
|
||||
#include <boost/limits.hpp> // for std::numeric_limits
|
||||
#include <boost/mpl/assert.hpp> // for BOOST_MPL_ASSERT_RELATION
|
||||
#include <boost/mpl/assert.hpp> // for BOOST_MPL_ASSERT_RELATION,etc.
|
||||
#include <boost/mpl/bool.hpp> // for boost::mpl::bool_
|
||||
#include <boost/mpl/bitwise.hpp> // for boost::mpl::bitor_, shift_left
|
||||
#include <boost/mpl/equal_to.hpp> // for boost::mpl::equal_to
|
||||
#include <boost/mpl/int.hpp> // for boost::mpl::int_
|
||||
#include <boost/mpl/integral_c.hpp> // for boost::mpl::integral_c
|
||||
#include <boost/mpl/next_prior.hpp> // for boost::mpl::prior
|
||||
#include <boost/mpl/range_c.hpp> // for boost::mpl::range_c
|
||||
|
||||
#include <cstddef> // for std::size_t
|
||||
#include <ios> // for std::hex
|
||||
#include <iostream> // for std::cout
|
||||
#include <ostream> // for std::endl
|
||||
|
||||
|
||||
// Control if events will be printed conventionally, or just logged.
|
||||
#ifndef CONTROL_SHOW_TYPES
|
||||
#define CONTROL_SHOW_TYPES 0
|
||||
#endif
|
||||
|
||||
// Logging
|
||||
#if CONTROL_SHOW_TYPES
|
||||
#define PRIVATE_SHOW_MESSAGE( m ) std::cout << m << std::endl
|
||||
#else
|
||||
#define PRIVATE_SHOW_MESSAGE( m ) BOOST_TEST_MESSAGE( m )
|
||||
#endif
|
||||
|
||||
|
||||
// Custom types/templates, helper functions, and objects
|
||||
namespace
|
||||
{
|
||||
|
||||
// A big one
|
||||
boost::uintmax_t const one = 1u;
|
||||
|
||||
// List the ranges of template parameters tests (ranges are half-open)
|
||||
int const max_offset = std::numeric_limits<boost::uintmax_t>::digits;
|
||||
|
||||
typedef boost::mpl::range_c<std::size_t, 0, max_offset> high_bit_offsets;
|
||||
typedef boost::mpl::range_c<std::size_t, 1, max_offset + 1> low_bit_lengths;
|
||||
typedef boost::mpl::range_c<int, 0, max_offset> high_bit_offsets;
|
||||
typedef boost::mpl::range_c<int, 0, max_offset + 1> low_bit_lengths;
|
||||
typedef boost::mpl::range_c<int, 1, max_offset + 1> special_low_bit_lengths;
|
||||
|
||||
// List a range with out-of-service values
|
||||
typedef boost::mpl::range_c<int, -10, max_offset + 11> wild_bit_lengths;
|
||||
|
||||
// Use SFINAE to check if a particular parameter is supported
|
||||
template < typename ValueT, template<ValueT> class Tmpl, ValueT Value >
|
||||
bool
|
||||
print_out_template( Tmpl<Value> const &, ValueT setting, char const
|
||||
*template_name, typename Tmpl<Value>::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 " << template_name << "<" << setting <<
|
||||
"> specialization with type '" << typeid(typename
|
||||
Tmpl<Value>::value_type).name() << "' and value '" << std::hex <<
|
||||
Tmpl<Value>::value << "'." );
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename ValueT, typename T >
|
||||
bool
|
||||
print_out_template( T const &, ValueT setting, char const *template_name )
|
||||
{
|
||||
PRIVATE_SHOW_MESSAGE( "There is no " << template_name << "<" << setting <<
|
||||
"> specialization." );
|
||||
return false;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
@ -46,14 +96,18 @@ BOOST_AUTO_TEST_SUITE( integer_mask_tests )
|
||||
// Check the bit-masks of one offset bit
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE( high_bit_mask_test, T, high_bit_offsets )
|
||||
{
|
||||
typedef boost::mpl::integral_c<typename
|
||||
boost::high_bit_mask_t<T::value>::least, 1u> one_type;
|
||||
typedef boost::mpl::shift_left<one_type, T> result_type;
|
||||
|
||||
BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t<T::value>::high_bit, ==,
|
||||
(one << T::value) );
|
||||
result_type::value );
|
||||
BOOST_MPL_ASSERT_RELATION( boost::high_bit_mask_t<T::value>::high_bit_fast,
|
||||
==, (one << T::value) );
|
||||
==, result_type::value );
|
||||
}
|
||||
|
||||
// Check the bit-masks of a block of low-valued bits
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths )
|
||||
// Check the bit-masks of a block of low-valued bits, non-zero block-lengths
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, special_low_bit_lengths )
|
||||
{
|
||||
// One can express (2^x - 1) in two ways
|
||||
// 1. (1 << x) - 1
|
||||
@ -62,10 +116,51 @@ BOOST_AUTO_TEST_CASE_TEMPLATE( low_bits_mask_test, T, low_bit_lengths )
|
||||
// when x is the number of bits in the register. However, that last case
|
||||
// gives warnings about the sole bit flowing past the register. Applying
|
||||
// distributive property backwards gives [2], which works without overflow.
|
||||
typedef typename boost::mpl::prior<T>::type shift_type;
|
||||
typedef boost::mpl::integral_c<typename
|
||||
boost::low_bits_mask_t<T::value>::least, 1u> one_type;
|
||||
typedef boost::mpl::shift_left<one_type, shift_type> high_bit_type;
|
||||
typedef typename boost::mpl::prior<high_bit_type>::type low_bits_type;
|
||||
typedef boost::mpl::bitor_<high_bit_type, low_bits_type> result_type;
|
||||
|
||||
BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t<T::value>::sig_bits, ==,
|
||||
(one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) );
|
||||
result_type::value );
|
||||
BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t<T::value>::sig_bits_fast,
|
||||
==, (one << ( T::value - 1u )) | (( one << (T::value - 1u) ) - 1u) );
|
||||
==, result_type::value );
|
||||
}
|
||||
|
||||
// Check the bit-masks of a block of low-valued bits, zero block-length
|
||||
BOOST_AUTO_TEST_CASE( special_low_bits_mask_test )
|
||||
{
|
||||
// Just like "low_bits_mask_test" above, except that the shifts are negative
|
||||
// when the bit-count is zero. That causes a lot of warnings and errors, so
|
||||
// special-case that bit-count.
|
||||
BOOST_MPL_ASSERT_RELATION( boost::low_bits_mask_t<0u>::sig_bits, ==, 0 );
|
||||
BOOST_MPL_ASSERT_RELATION(boost::low_bits_mask_t<0u>::sig_bits_fast, ==, 0);
|
||||
}
|
||||
|
||||
// Check the specialization type status of given bit-offsets/lengths
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE( confirm_bounds_test, T, wild_bit_lengths )
|
||||
{
|
||||
typedef boost::integer_hi_mask<T::value> hi_type;
|
||||
typedef boost::mpl::int_<hi_type::bit_offset> hi_offset_type;
|
||||
typedef boost::mpl::bool_<hi_type::is_specialized> special_hi_type;
|
||||
|
||||
BOOST_MPL_ASSERT( (boost::mpl::equal_to< hi_offset_type, T >) );
|
||||
BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_hi_type,
|
||||
boost::mpl::bool_<(T::value >= 0) && (T::value < max_offset)> >) );
|
||||
BOOST_CHECK_EQUAL( print_out_template(hi_type(), hi_offset_type::value,
|
||||
"integer_hi_mask"), special_hi_type::value );
|
||||
|
||||
typedef boost::integer_lo_mask<T::value> lo_type;
|
||||
typedef boost::mpl::int_<lo_type::bit_count> lo_length_type;
|
||||
typedef boost::mpl::bool_<lo_type::is_specialized> special_lo_type;
|
||||
|
||||
BOOST_MPL_ASSERT( (boost::mpl::equal_to< lo_length_type, T >) );
|
||||
BOOST_MPL_ASSERT( (boost::mpl::equal_to< special_lo_type,
|
||||
boost::mpl::bool_<(T::value >= 0) && (T::value <= max_offset)> >) );
|
||||
BOOST_CHECK_EQUAL( print_out_template(lo_type(), lo_length_type::value,
|
||||
"integer_lo_mask"), special_lo_type::value );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
Reference in New Issue
Block a user