问题
I have implemented a routing to print out all of the options that are available in my boost::program_options
objects along with their current values by iterating over the po::variable_map
.
With this I can directly print the long name of the option along with its value. However, I do not know, how to retrieve the short option name from the long option name (i.e. -h from --help). Any suggestions how to do this?
回答1:
I remember describing in a recent answer why variable_map
is "too late" to know about the option descriptions:
- Boost. Handy variables_map. Taking advantage of having specified the type in the options_desctription
In short, the variable_map sits in the Storage Component of the library and as such is isolated from the Option Descriptions (which lives in the Options Description Component).
What can you do?
You could work with the intermediate results, the raw output from the Parsers Component:
The results of parsing are returned as an instance of the parsed_options class. Typically, that object is passed directly to the storage component. However, it also can be used directly, or undergo some additional processing
So, let's try to work out a sample here:
po::parsed_options const intermediate = po::parse_command_line(ac, av, desc);
//////////////////////////////////
// print the extended usage info as per the question
//
for (auto& entry : intermediate.options)
{
po::option_description const& opt = desc.find(entry.string_key, false, false, false);
std::cout << "\nActual tokens involved: ";
for (auto& tok : entry.original_tokens)
std::cout << "'" << tok << "' ";
for (std::string const& v : entry.value)
std::cout << "\nAssociated value: " << v;
std::cout << "\n-----------------------------------------------------------\n";
std::cout << "opt.format_name() : " << opt.format_name() << "\n";
std::cout << "opt.long_name() : " << opt.long_name() << "\n";
std::cout << "opt.canonical_display_name('-'): " << opt.canonical_display_name(cls::allow_dash_for_short) << "\n";
std::cout << "opt.canonical_display_name('/'): " << opt.canonical_display_name(cls::allow_slash_for_short) << "\n";
std::cout << "opt.canonical_display_name('--'): " << opt.canonical_display_name(cls::allow_long) << "\n";
}
Note: with the lookup by key, you can practically also use the
variable_map
after all.
Prints e.g.
Actual tokens involved: '-C' '42'
Associated value: 42
-----------------------------------------------------------
opt.format_name() : -C [ --compression ]
opt.long_name() : compression
opt.canonical_display_name('-'): -C
opt.canonical_display_name('/'): /C
opt.canonical_display_name('--'): --compression
Actual tokens involved: '--name' 'santa'
Associated value: santa
-----------------------------------------------------------
opt.format_name() : -n [ --name ]
opt.long_name() : name
opt.canonical_display_name('-'): -n
opt.canonical_display_name('/'): /n
opt.canonical_display_name('--'): --name
Compression level was set to 42.
Live On Coliru
#include <boost/program_options.hpp>
#include <boost/program_options/detail/parsers.hpp>
#include <iostream>
namespace po = boost::program_options;
namespace cls = po::command_line_style;
int main(int ac, char** av) {
// Declare the supported options.
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("name,n", po::value<std::string>(), "specify the name")
("compression,C", po::value<int>(), "set compression level")
;
po::variables_map vm;
po::parsed_options const intermediate = po::parse_command_line(ac, av, desc);
//////////////////////////////////
// print the extended usage info as per the question
//
for (auto& entry : intermediate.options)
{
po::option_description const& opt = desc.find(entry.string_key, false, false, false);
std::cout << "\nActual tokens involved: ";
for (auto& tok : entry.original_tokens)
std::cout << "'" << tok << "' ";
for (std::string const& v : entry.value)
std::cout << "\nAssociated value: " << v;
std::cout << "\n-----------------------------------------------------------\n";
std::cout << "opt.format_name() : " << opt.format_name() << "\n";
std::cout << "opt.long_name() : " << opt.long_name() << "\n";
std::cout << "opt.canonical_display_name('-'): " << opt.canonical_display_name(cls::allow_dash_for_short) << "\n";
std::cout << "opt.canonical_display_name('/'): " << opt.canonical_display_name(cls::allow_slash_for_short) << "\n";
std::cout << "opt.canonical_display_name('--'): " << opt.canonical_display_name(cls::allow_long) << "\n";
}
//////////////////////////////////
po::store(intermediate, vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return 1;
}
if (vm.count("compression")) {
std::cout << "Compression level was set to "
<< vm["compression"].as<int>() << ".\n";
} else {
std::cout << "Compression level was not set.\n";
}
}
来源:https://stackoverflow.com/questions/32254979/boost-program-options-short-long-parameter-names