With command line options, I can do the following:
po::variables_map vm;
auto parsedOptions = po::command_line_parser(argc, argv).options(optionsDescription1).allow_unregistered().run();
po::store(parsedOptions, vm);
po::notify(vm);
auto unregistered = po::collect_unrecognized(parsedOptions.options, po::include_positional);
po::variables_map vm2;
auto parsedOptions2 = po::command_line_parser(unregistered).options(optionsDescription2).run();
po::store(parsedOptions2, vm2);
po::notify(vm2);
This works fine, because collect_unregistered()
collects the command line tokens exactly as it appeared in the command line. However, it doesn't work for config files. I can parse a config file allowing unregistered options, but when I collect the unregistered options, I get a result that I cannot use.
po::variables_map vm;
auto parsedOptions = po::parse_config_file<char>(filename, optionsDescription1, true);
po::store(parsedOptions, vm);
po::notify(vm);
auto unregistered = po::collect_unrecognized(parsedOptions.options, po::include_positional);
In this case I get the names and values of the options listed. For example, if the config file contained the following options:
unregistered_option1=value1
unregistered_option2=value2
Then I get the values unregistered_option1
, value1
, unregistered_option2
, value2
in the string vector unregistered
. Boost's parser cannot do anything useful with this format. Is there any way to parse this list (i.e. parse all the options that were unrecognized by the first options_description
with a different options_description
)? Of course I can just parse the file again with the second options_description
with allow_unregistered
set, but then I can't check for options unknown to both descriptions.
You don't have to rely on the imperfections of collect_unrecognized()
return value, you can always detect, handle and reconstruct the options yourself, as the result of parse_config_file()
keeps the observed relationship for the unknown options:
auto parsed_options = parse_config_file(ifs, config_file_options, true);
store(parsed_options, vm);
...
for (const auto& o : parsed_options.options) {
if (vm.find(o.string_key) == vm.end()) {
// an unknown option
cout << o.string_key << "=" << o.value << "\n";
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With