Browse DevX
Sign up for e-mail newsletters from DevX


Revisiting Heterogeneous Containers -2 : Page 2




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Presenting the Problem
There's no need to explain why heterogeneous containers are useful. Yet the current techniques of imitating heterogeneity aren't satisfactory. Take for example the shared_ptr approach. Although this is safer than using raw pointers, it still forces you to use the cumbersome pointer syntax. Worse yet, it only allows you to store objects that belong to the same class hierarchy. What if you want to store unrelated datatypes such as int, std::string, and CDialog in the same container? Theoretically, you can use tuples for this purpose. However, tuples aren't real containers—they have a statically fixed size and they hold, at most, ten elements. Does that mean you're still stuck with the burdensome container of pointers approach? Not necessarily. Class boost::any, which is part of the Boost.Any library, overcomes many of the limitations of traditional heterogeneous containers.

Anything Goes
boost::any allows for type-safe storage and the retrieval of arbitrary types. The main difference between this class and other indiscriminate types (like unions, variant_t, etc.) is that the caller must know the exact type of the value stored in boost::any in order to access it.

Author's Note: Before you can use boost::any, you need to download the relevant boost libraries and install them. Note also that according to the Boost convention, class any and its related helper functions are declared in namespace boost.

boost::any has a default constructor which creates an empty any object, and another non-explicit constructor which takes an object of an arbitrary type. The copy constructor and assignment operator enable you to copy and assign any type of object to any:

boost::any a; a=10; a=std::string("I'm a string"); boost::any a2(a);

You can store any object that meets the copy-constructible and assignable requirements in any. To access the value stored in any, use the boost::any_cast function. any_cast is similar to operator dynamic_cast: its first argument is a type name, and the second is the actual any object. If the type name matches the object's type, any_cast returns a reference to the stored object. Otherwise, it throws a boost::bad_any_cast exception:

try { std::string test=boost::any_cast<std::string> (a); } catch(boost::bad_any_cast & e) { cout<<"it's not a string!" <<endl; }

any_cast also has a pointer version which doesn't throw. If the types of the target and the source don't match, a NULL pointer is returned:

string *ptest=boost::any_cast<string> (&a); if(ptest) { cout<<*ptest<<endl; } else { cout<<"it's not a string!" <<endl; }

any grants access to the stored object only if you know its type. Since any can contain at most one object at a time, assigning a new object to it overrides the previously stored value (and its type). The any_cast operations above are successful because the last object assigned to any was a string.

Thanks for your registration, follow us on our social networks to keep up-to-date