I am writing a data packer for my game. The idea is to write something that can pack attributes, stream data over the network and other areas where data packing can be desirable. I have used a version of http://cplusplus.com/articles/zb07M4Gy/ to achieve part of my goal. My code looks like:
namespace detail
{
// Determine whether _Type is signed or unsigned.
// _Result is then either a signed or unsigned char
template < typename _Type >
struct sign
{
typedef typename std::_If< std::tr1::is_unsigned< _Type >::value, unsigned char, signed char >::_Type _Result;
};
}
// Template for packing and unpacking data
// at bit and byte level
template < typename _Type >
struct packer
{
typedef typename _Type value_type;
static const int num_bytes = sizeof(value_type);
static const int num_bits = num_bytes * CHAR_BIT;
union
{
value_type packed_value;
typename detail::sign< value_type >::_Result byte[num_bytes];
};
};
My question is, how can I extend this code to allow access to the individual bits without bit shifting? I cannot use std::bitset since it has a non-trivial constructor and an array of bool would result in allocating a byte for each entry instead of a bit.
Ideally I would like to avoid bit setting/checking macros (although, it does seem my hands may be tied). There are portability and endian issues, but those aside, is there a way to achieve my goal?
An idea I had was to use something like:
template< int _NumBits >
struct bit_field
{
bit_field< _NumBits - 1 > the_other_bits;
int value : 1;
int operator[](const int in_index)
{
return reinterpret_cast< int* >(this)[index];
}
};
template< >
struct bit_field< 0 >
{
int value : 1;
int operator[](const int in_index)
{
return reinterpret_cast< int* >(this)[index];
}
};
Which would recursively build an array. However the problem with this (obviously) is alignment, which for this struct is 4bytes in MSVC10 giving the packer struct a total of 132 bytes, which is obviously not ideal when working with a 4 byte integer…
Any suggestions (including “man up and use bit shifting”…) are welcome.
You can use bitfields:
and then in your union