C++ – Setting boost dynamic_bitset from a string


Dynamic bitset

I have a use case where i need to populate

boost::dynamic_bitset<unsigned char> , from a std::string buffer.

Can you suggest as to how to go about this. So I need to come up with a function

void populateBitSet (std::string &buffer, 
            boost::dynamic_bitset<unsigned char> & bitMap) {

     //populate bitMap from a string buffer

Best Solution

If you have binary data like this:

string buffer = "0101001111011";

You want to initialize it like this (turns out there's a constructor that handles this case):

void populateBitSet (std::string &buffer, boost::dynamic_bitset<unsigned char> & bitMap) 
   bitMap = boost::dynamic_bitset<unsigned char> (buffer);

If you want the raw data, use the iterator constructor:

void populateBitSet (std::string &buffer, boost::dynamic_bitset<unsigned char> & bitMap) 
   bitMap = boost::dynamic_bitset<unsigned char> (buffer.begin(), buffer.end());

These do end up allocating the needed memory twice, so you might be better off with a stack allocation and a swap. Or you just can wait until C++0x and let the move semantics do their thing.

// Unecessary in C++0x
void populateBitSet (std::string &buffer, boost::dynamic_bitset<unsigned char> & bitMap) 
   boost::dynamic_bitset<unsigned char> localBitmap(buffer.begin(), buffer.end());

Edit: To clarify why the first versions allocate twice as much memory:

Take a look at another way to write the first version:

typedef boost::dynamic_bitset<unsigned char> bits; // just to shorten the examples.
void populateBitSet (std::string &buffer, bits &bitMap) 
   const bits &temp = bits(buffer); // 1. initialize temporary
   bitMap = temp; // 2. Copy over data from temp to bitMap

If you put these two lines together, as in the first example, you still get a temporary constructed on the stack, followed by an assignment. In 1. boost needs to allocate enough memory for the entire set of bits. In 2, boost needs to allocate again enough memory to hold that same set of bit and then copy the values over. It's possible that bitMap already has enough memory, so it may not always need to reallocate, but it's also possible that it will free its backing memory and reallocate from scratch anyway.

Most containers that fit the stl mold also have a swap function that you can use in place of assignment when you intend to throw away one side of the swap. These are usually O(1) and non-throwing as they often just involve swapping some pointers. See this GotW for another reason why these are useful.

In C++0X, you'll be able to use assignment, and still get the advantages of swap. Since you can overload on r-values (like the temporary), the container know that when you assign a temporary, it knows that it can cannibalize the temp and basically do a swap. The Visual Studio Team Blog has covered rvalues and move semantics quite well here.