The boost:assign framework is a collection of utilities to facilitate standard (STL) containers addition of data. I will try to brush an overview of its most important features.
The easiest one is the addition of operator+=() to standard containers. One simply need to include the associated boost::assign header that matches the container to augment. It will then allow the use of += operator followed by a comma separated list of elements. For example, adding a series of integers to a vector:
#include <boost/assign/std/vector.hpp> using namespace std; using namespace boost::assign; ... vector<int> values; values += 1,2,3,4,5,6,7,8,9;
The next feature is the operator()() that allow a series of entries to be added to a container. In the following example, we include the header for the “insert” function to allow a series of data to effectively being inserted into a container. An equivalent push_back function is also available.
#include <boost/assign/list_inserter.hpp> using namespace std; using namespace boost::assign; ... map<string,int> months; insert( months ) ( "january", 31 )( "february", 28 ) ( "march", 31 )( "april", 30 ) ( "may", 31 )( "june", 30 ) ( "july", 31 )( "august", 31 ) ( "september", 30 )( "october", 31 ) ( "november", 30 )( "december", 31 );
So far we have seen ways to add data to a variable declared container. But boost::assign also provides a mechanism to initiate a constant container, through the use of a function named list_of. Here’s an example:
#include <boost/assign/list_of.hpp> #include <list> using namespace std; using namespace boost::assign; ... const list<int> primes = list_of(2)(3)(5)(7)(11);
Some containers require the uses of an adapter for the data to be properly passed in. As it is the case for the std::stack<> container for instance. In such cases, it’s only a matter of ending the list of data using the to_adapter() function, like so:
const stack<string> names = list_of( "Hello" )( "World")( "!!!" ).to_adapter();
I just presented the main ways of adding data to a container. boost::assign also provides an array of tools to simplify even more the process.
One such tool is the repeat() function, that can be used inside an assign list to repeat a single value multiple times (or just once). Like so:
vector<int> v; v += 1,2,repeat(10,3),4,5;
The result of the previous command will add to the vector the values 1,2,3,3,3,3,3,4,5. repeat() is not limited to the operator+=() format. It can also be used in a list_of like so:
A quite powerful tool is the range() one. It can be used to pass iterators (beginning & end) from an other container, to insert the data from that container in the built list. Like so:
v = list_of(1).range(v2).range(v2.begin(),v2.end())(4);
In the previous example, the content of the v2 container is added twice to v. The first time by simply passing the container itself to range() which causes the whole container to be parsed in the list, and the second time by passing the beginning and ending iterator of that same v2 container.
There’s a few more utilities included with boost::assign, which might be of lesser uses. But just with the main ones I just mentioned in this post, I can see my handling of containers is going to be drastically different from now on.
I’m also contemplating in abandoning my old static const pure array (with assert on array length) for all those small local tables of data. Replacing them with static const std:vectors initialized with a list_of seems a much safer way to go from now on.