Boost program options iterate over variables_map
boost variable_map
use boost::any
as the value so you can try to use boost::any_cast<T>
to find out the type.
perhaps something like this
for (const auto& it : vm) {
std::cout << it.first.c_str() << " ";
auto& value = it.second.value();
if (auto v = boost::any_cast<uint32_t>(&value))
std::cout << *v;
else if (auto v = boost::any_cast<std::string>(&value))
std::cout << *v;
else
std::cout << "error";
}
boost::program_options::variable_map
is essentially an std::map<std::string, boost::any>
, which means it uses type erasure to store the values. Because the original type is lost, there's no way to extract it without casting it to the correct type. You could implement a second map
that contains the option name as key, and the extraction function as value, allowing you to dispatch the value to the appropriate extractor at runtime.
using extractor = std::map<std::string, void(*)(boost::variable_value const&)>;
or
using extractor = std::map<std::string,
std::function<void(boost::variable_value const&)>;
if your extractors are more complicated and will not convert to a simple function pointer. An example of an extractor that'll print a uint32_t
is
auto extract_uint32_t = [](boost::variable_value const& v) {
std::cout << v.as<std::uint32_t>();
};
Then your loop would look like this:
for (const auto& it : vm) {
std::cout << it.first.c_str() << " "
extractor_obj[it.first](it.second)
std::cout << "\n";
}
Here's a live demo with some made up types, but it's close enough to your use case that you should be able to apply something similar.