I have a program that use boost::program_options to parse a command line. One of the parameter is the name of an AMQP exchange, and a default value is provided. For testing purposes, I would like to override this AMQP exchange name with an empty string (to use a default exchange).
I don't know how to pass an empty string to boost::program_options. Is that possible? Without modifying the source code? If not, what do you recommend?
Here is a minimum working example code :
#include <boost/program_options.hpp>
namespace po = boost::program_options;
constexpr auto EXECUTABLE_DESCRIPTION =
"Minimum working example showing my difficulties while trying to "
"pass an empty string as an argument to boost::program_options.";
int main(int argc, char **argv) {
std::string elkExchange;
po::options_description config("");
config.add_options()
("amqp.exchange",
po::value<std::string>(&elkExchange)
->default_value("default-exchange"), // default value used in prod
"Exchange on which to send the events");
// do the parsing
po::options_description cmdline_options(std::string{EXECUTABLE_DESCRIPTION});
cmdline_options.add(config);
po::variables_map args;
store(po::command_line_parser(argc, argv).
options(cmdline_options).run(), args);
notify(args);
// debug display
std::cout << "Send event on elk.exchange: {" << elkExchange << "}" << std::endl;
// real application code here ...
return EXIT_SUCCESS;
}
Here is what I would like to do:
# default value is used as expected
$ ./boost/empty-string-in-cli/exec
Send event on elk.exchange: {default-exchange}
# override with non-empty value work as expected
$ ./boost/empty-string-in-cli/exec --amqp.exchange='custom'
Send event on elk.exchange: {custom}
# here is where the troubles begin
$ ./boost/empty-string-in-cli/exec --amqp.exchange=''
terminate called after throwing an instance of 'boost::wrapexcept<boost::program_options::invalid_command_line_syntax>'
what(): the argument for option '--amqp.exchange' should follow immediately after the equal sign
Aborted (core dumped)
Thanks in advance : )
To my surprise, the adjacent long option parser absolutely forbids the =
sign with a zerolength value, see the code on https://github.com/boostorg/program_options/blob/develop/src/cmdline.cpp#L520.
Therefore it seems your only recourse is to avoid using the adjacent-value syntax:
for EXCHANGE in foo bar ''; do ./build/sotest --amqp.exchange "$EXCHANGE"; done
Prints
Send event on elk.exchange: {foo}
Send event on elk.exchange: {bar}
Send event on elk.exchange: {}