Browse DevX
Sign up for e-mail newsletters from DevX


Revisiting Heterogeneous Containers -3 : Page 3

Creating a Heterogeneous Container
The following example uses a vector of any to store four unrelated objects:

using std::vector; 
using std::string;
using std::make_pair;
using std::for_each;
int main()
 vector<boost::any> bag;
 //store a pair
 bag.push_back(make_pair(string("PAGE_SIZE"), 1024));
 for_each(bag.begin(), bag.end(), retrieve);

bag really looks like a heterogeneous container! But how do you access the elements stored in it? First, access the vector's elements as usual, using iterators (as shown in the example) or the [] notation. Next, use the any_cast function to retrieve the value stored in each element:

using std::string;
using std::map;
using std::cout;
using std::endl;

void retrieve(boost::any & a)
 if(string *pstr = boost::any_cast<string>(&a))
  cout<<"string is: "<< *pstr <<endl;
 else if (int *pi = boost::any_cast <int> (&a))
  cout<<"int: "<< *pi <<endl;
 else if ( myclass *pmc = boost::any_cast<myclass>(&a))
  cout<< "myclass: " <<endl;
 else if (map <string, int> *pmap
   =boost::any_cast<map<string, int> >(&a))
  cout<< "map<string, int>: " << pmap->first <<" " 
   << pmap>second >>endl;
  cout<< "unknown type" << endl;
Unlike dynamic_cast, boost::any supports non-polymorphic objects and built-in datatypes as well. There's no need to worry about performance either—as opposed to dynamic_cast, boost::any_cast actually uses static_cast under the hood, so it's pretty efficient.

Additional Member Functions
any's destructor destroys the object stored in it. However, because the destructor calls delete and never delete[], you should wrap pointers to arrays in an appropriate smart pointer before storing them in any.

The empty() member function returns a Boolean value indicating whether the any object contains a value:

boost:any anybody;
cout<<anybody.empty()<<endl; //display 'true'
any objects. Finally, the type() member function returns a reference to std::type_info which you can use in a typeid expression:

if (typeid(any1.type())==typeid(int))
 int val=boost::any_cast<int> (any1);

Safe and Efficient
boost::any brings STL containers closer to the SmallTalk-style concept of heterogeneous containers, with minimal performance overhead and without compromising type-safety. Remember that boost::any is also useful in other frameworks that require indiscriminate types. What's still missing in standard C++ is a reflection library that safely reconstructs objects and their types from a collection.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Thanks for your registration, follow us on our social networks to keep up-to-date