|
Boost : |
From: Emile Cormier (emilecormier_at_[hidden])
Date: 2006-03-15 21:56:33
Consider the following snippet:
template <uint8_t F, uint8_t L, class T, class R=T&, class I=T&>
class Bitfield
{
BOOST_STATIC_ASSERT( F < 8*sizeof(T) );
BOOST_STATIC_ASSERT( L < 8*sizeof(T) );
BOOST_STATIC_ASSERT( F <= L );
enum
{
FIRST = F, //!< Position of the first bit
LAST = L, //!< Position of the last bit
WIDTH = LAST - FIRST + 1, //!< Width in bits of the
Bitfield
VAL_MASK = (1 << WIDTH) - 1, //!< Mask applied against
assigned values
FIELD_MASK = VAL_MASK << FIRST //!< Mask of the field's bit
positions
};
};
What would be the most appropriate type for the F and L template
parameters? I had arbitrarily picked uint8_t because I felt that it
would big enough for a right-hand-side shift operand (at least until
they come up with processors supporting 512-bit registers). But since I
static-check the range of these compile-time constants, I don't see the
point in constraining them to uint8_t.
Is integral promotion performed on the right-hand-side operand of a
shift operator?
I'm thinking I should use (unsigned int) instead of (unsigned char), in
case Bitfield is later extended to support bit manipulations in
multi-word data.
P.S. I just spotted a problem that I forgot to fix in the latest draft I
just uploaded.
The problem is with:
VAL_MASK = (1 << WIDTH) - 1
With the arm-elf-gcc compiler, I get an error when WIDTH is 32. That
line needs to be replaced with:
VAL_MASK = ((1 << (WIDTH-1)) << 1) - 1
When WIDTH is 32, (1 << 31) << 1 == 0, so after the subtraction we get
VAL_MASK == -1, which is 0xffffffff when interpreted as unsigned. We
still get the desired result even though the second shift resulted in an
"overflow".
-- Emile Cormier emilecormier_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk