user9645
user9645

Reputation: 6806

How to parse boolean option in config file

Using boost 1_55, I have a bool_switch() option, which is defined as:

bpo::options_description opts;
opts->add_options()
    ("foo", bpo::bool_switch(), "Enable foo.");
opts_map = new bpo::variables_map;

And it is parsed on the command line by:

bpo::store(bpo::parse_command_line(argc, argv, opts), *opts_map);

And also parsed in a config file by:

ifstream ifs("foo.conf");
if (ifs.good()) {
    bpo::store(bpo::parse_config_file(ifs, opts), *opts_map);
    close(ifs);
}

The trouble is that it works fine on the command line by either specifying --foo or not, but it is always false (with second.defaulted() == true) when I put it in the config file. I have tried the following in the config file:

foo
foo=true
foo=1

Other types of options (e.g. bpo::value<ANYTYPE>() with or without composing()) work fine both on the command line and also in the config file, only bool_switch() options are not working.

Any idea what I'm doing wrong? Or can you not use bool_switch() options with parse_config_file()?

EDIT:

A workaround is to use a value() type with default_value() and implicit_value():

opts->AddOptions()("foo", bpo::value<bool>()->default_value(false)->implicit_value(true), "Enable foo.");

Upvotes: 3

Views: 2062

Answers (2)

Drew
Drew

Reputation: 21

I'm currently using Boost 1.58 and support for boolean switch options in a config file works just fine.

Config file (config.cfg):

log=ON

Code:

#include <fstream>
#include <boost/program_options.hpp>
#include <iostream>

namespace prog_opts = boost::program_options;

//Notified function
void option_verbose(bool opt) {
  std::cout << "Log ";
  if (opt)
    std::cout << "ON";
  else
    std::cout << "OFF";

  std::cout << "\n";
}

int main (int argc, char* argv[]) {

  prog_opts::options_description general("Options");

  general.add_options()
     ("log", prog_opts::bool_switch()->notifier(&option_verbose), "logging")
     ;

  // Assign the CLI args to the map
  prog_opts::variables_map cli_map;

  const prog_opts::basic_parsed_options< char >& cliopts = prog_opts::command_line_parser(argc, argv).options(general).run();

  prog_opts::store(cliopts , cli_map);

  // Get options from config
  std::ifstream infile("config.cfg", std::ifstream::in);
  store(parse_config_file(infile, general), cli_map);

  notify(cli_map);
}

From using this, it appears that the behavior is:

  1. If your option is present on the command line then that overrides the config file.
  2. If your option is not present on the command line then the config file option value is used instead.

In the example code with log=ON in the config file, the option will always be ON. With it set to OFF, the option will only be enabled when running your application with the option --log.

Hope this helps.

Upvotes: 2

Sam Miller
Sam Miller

Reputation: 24174

I don't think what you're trying to do is presently allowed. Vladimir, the author of the program options library states

I've changed bool_switch so that it does not accept any arguments. This also solves the problem with "arg (=0)" output.

There's one possible problem. For command line, we most likely don't want explicit value for bools. But in config file, the value is always present. This is the only case I know where single options description for command line and other sources is problematic -- if you describe an option with bool_switch, it can't be specified in config file.

Let's see if that's a problem.

Note that this statement is nearly 10 years old, but I couldn't find any evidence it's no longer true when inspecting the source code in 1.55.

Upvotes: 1

Related Questions