The C++ Boost Libraries Part 6 – boost::any

December 6, 2009 – 3:41 pm

In C++ if you have a variable that you say is of type “Person” (for instance), you can be fairly certain (more or less) that it always actually contains a Person (or perhaps a subclass of Person. If you have a container of Persons, then you know (more or less) that every member is also a Person (or a subclass).

This is all very good, prevents a lot of runtime errors, and generally makes C++ a great language if you care about correctness. But sometimes, very rarely, you actually want to store a whole bunch of messy, unrelated types in a container without trying to ram them into some sort of class hierarchy. Parsers are a good example of this. It is often convenient just to chuck tokens of various types into a data structure for later processing without worrying too much about the specific type (string, int, float, etc).

boost::any is a small class that can hold values from almost any type, designed for just such messy applications. Using boost::any is very simple:

1
2
boost::any a1 = std::string("Moose");
boost::any a2 = 6;

Of course, getting the values back again is a little harder.

1
2
3
4
5
6
7
8
9
try
{
	std::string v1 = boost::any_cast< std::string >(a1); // this works, a1 is a string
	std::string v2 = boost::any_cast< std::string >(a2); // nope, will throw an exception at runtime
}
catch ( const boost::bad_any_cast& e )
{
	// tried to any_cast into something that wouldn't go
}

Of course, you can query a boost::any for the typeid of the stored object. Just don’t do it when Scott Meyers is in the vicinity.

1
2
3
4
5
std::string v;
if ( a1.type() == typeid(std::string) )
{
	v = boost::any_cast< std::string >( a1 ); // this should never throw, since we checked first
}

A single boost::any is perhaps not that useful, but a container of them can store almost anything we want:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef std::vector< boost::any > AnyVector;
AnyVector values;
 
values.push_back( 5 );
values.push_back( std::string("Hello") );
values.push_back( 5.3 );
 
try 
{
	for ( AnyVector::const_iterator p = values.begin();
			p != values.end();
			++p )
	{
		if ( p->type() == typeid(int) )
			cout << "Int = " << any_cast<int>(*p) << endl;
		else if ( p->type() == typeid(std::string) )
			cout << "String = " << any_cast<string>(*p) << endl;
		else 
		{
			cout << "Unhandled type: " << p->type().name() << endl;
		}
	}
} 
catch ( const boost::bad_any_cast &e )
{
	cout << "Bad any_cast<>" << e.what() << endl;
}

Any type that you put into a boost::any must be copy constructable (the any makes a copy, not a reference). You also have to make sure that its destructor doesn’t throw (but of course you do that anyway!)

Although I wouldn’t recommend boost::any for everyday use, it does come into its own when the only alternative is a huge class structure or (even worse) void *s.

Related posts:

  1. The C++ Boost Libraries Part 5 – boost::filesystem The standard C++ iostreams library is very good (well, some...
  2. Using Exceptions in C++ C++ is big – it has been said that any...

Related posts brought to you by Yet Another Related Posts Plugin.

  1. 5 Responses to “The C++ Boost Libraries Part 6 – boost::any”

  2. Might as well go back to C programming with that abomination!

    By Aza on Dec 6, 2009

  3. Maybe, but at least it is a step up from void *.

    By Andrew on Dec 6, 2009

  4. Actually it reminded me more of Visual Basic programming than C…

    Oh god, did I just out myself as having some VB knowledge…

    By Stu on Dec 7, 2009

  5. I always have horrible flashbacks to the COM VARIANT type when I see that thing. I’m sure it’s handy in some cases, but it still make me itch.

    By James Wells on Dec 8, 2009

  6. Yeh… I guess its at least better than void *….

    By Chuck on Dec 16, 2009

Post a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word