How to print boost::any to a stream?

Frank picture Frank · Jul 12, 2010 · Viewed 9.8k times · Source

I have a Map std::map<std::string, boost::any>, which comes from the boost::program_options package. Now I would like to print the content of that map:

for(po::variables_map::const_iterator it = vm.begin(); it != vm.end(); ++it) {
  std::cerr << it->first << ": " << it->second << std::endl;
}

Unfortunately, that is not possible because boost::any doesn't have an operator<< defined.

What is the easiest way to print that map?

I could define my own output operator for any that automatically tries to cast each any to an int, then double, then string, etc., each time ignoring errors and trying to cast until the cast is successful and I can print as the specified type.

But there should be an easier method in Boost? I'd need something like a reverse lexical_cast...

Answer

hkaiser picture hkaiser · Jul 12, 2010

You could use boost::spirit::hold_any instead. It's defined here:

#include <boost/spirit/home/support/detail/hold_any.hpp>

and is fully compatible with boost::any. This class has two differences if compared to boost::any:

  • it utilizes the small object optimization idiom and a couple of other optimization tricks, making spirit::hold_any smaller and faster than boost::any
  • it has the streaming operators (operator<<() and operator>>()) defined, allowing to input and output a spirit::hold_any seemlessly.

The only limitation is that you can't input into an empty spirit::hold_any, but it needs to be holding a (possibly default constructed) instance of the type which is expected from the input.