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;
bag.push_back(string());
bag.push_back(80);
bag.push_back(myclass());
//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;
}
else
{
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 eitheras 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.