Boost logo

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