Manage command-line options with Boost Program Options

In command-line program, we often faces problems with the management of command-line options. When you have a few options, it's not a problem. But when writing complex programs with tens of options (or hundreds), it starts to be too complicated to manage by hand. That's where Boost Program Options enters the game!

Boost Program Options is one of the Boost C++ Libraries. It is a very powerful library to handle command-line options. You define all the options of the program and then Boost Program Options takes care of all. It parses the command line, handles errors, gets values and even displays help. It is not a perfect library. But it is very complete that will answer most of the common needs.

This library is not header-only. You will need to build the library and link your program with the library.

Getting started

In this article, I will use po as an abbreviation of boost::program_options and all source will contains this namespace alias:

namespace po = boost::program_options;

First of all, it is necessary to create an instance of po::option_description:

po::options_description description("MyTool Usage");

description.add_options()
    ("help", "Display this help message")
    ("version", "Display the version number");

The parameter to the constructor is the title of the options. To add options, you use the add_options() function and append all your options, each one surrounded with parenthesis. Here, we declared two options (help and version). They can be set with --help and --version.

Then, you can parse the command line by declaring a po::variables_map to store the variables and parse the command line into that storage:

po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(description).run(), vm);
po::notify(vm);

Then, you can easily verify if an option has been set by using the count(const std::string& name) function on the vm object:

if(vm.count("help")){
    std::cout << description;
}

You can use operator on the description to output all the options of program.

Short options

By default, all the options are accessed by using -- in front of them. You can also specify a short version for each option:

description.add_options()
    ("help,h", "Display this help message")
    ("version,v", "Display the version number");

With that, you can display with either --help or -h. Even if you select help with -h, you can still verify if help has been set with count("help").

Option with value

Boost Program Options can also handle option that need a specific value. Lets add a compression option:

description.add_options()
    ("help,h", "Display this help message")
    ("compression,c", po::value<int>(), "Compression level")
    ("version,v", "Display the version number");

You can then get the value of option easily:

if(vm.count("compression")){
    std::cout << "Compression level " << vm["compression"].as<int>() << std::endl;
}

For the story, the option value are stored as boost::any. You can get the value of the option by using operator[] on the po::variables_map. You can get the value type with the as function with the type you need.

On the command line, the value can be set with --compression 10, -c 10 or -c10.

You can also configure a default value for an option:

description.add_options()
    ("help,h", "Display this help message")
    ("compression,c", po::value<int>()->default_value(5), "Compression level")
    ("version,v", "Display the version number");

With that, if the option is not set on the command line, the option has the specified value. With that, the option is always defined.

Finally, you can also set an implicit value. This is the value of the option is the option is set to the command line without a value (--compression or -c):

description.add_options()
    ("help,h", "Display this help message")
    ("compression,c", po::value<int>()->default_value(5)->implicit_value(10), "Compression level")
    ("version,v", "Display the version number");

Positional options

It is often convenient to have a list of files on the command line. These options does not have a name. In Boost Program Options, these options are called positional options. You have to declare them in the describe as any other action. For example, for a list of files:

description.add_options()
    ("help,h", "Display this help message")
    ("compression,c", po::value<int>()->default_value(5)->implicit_value(10),"Compression level")
    ("input-files", po::value<std::vector<std::string>>(), "Input files")
    ("version,v", "Display the version number");

Then, you have to declare it as positional and then finally specify it when parsing the command-line:

po::positional_options_description p;
p.add("input-files", -1);
po::variables_map vm;
po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm);
po::notify(vm);

The positional options values are retrieved the exact same way as other options:

if(vm.count("input-files")){
    std::vector<std::string> files = vm["input-files"].as<std::vector<std::string>>();
    for(std::string file : files){
        std::cout << "Input file " << file << std::endl;
    }
}

Wrap-Up

In this article, we saw the most important aspects of Boost Program Options. With these notions, you can start using this great library. If you need more information about the library, you can read the official documentation that is very well made.

You can download the final sources of this article on Github: v1.cpp

Related articles

  • Compute command-line arguments with Apache Commons CLI
  • Boost 1.48.0 has been released
  • eddic 0.5.1 : Better assembly generation and faster parsing
  • Use Boost enable_if to handle ambiguous function overload return types
  • C++ Containers Benchmark: vector/list/deque and plf::colony
  • eddic 1.2.4: New Boost Spirit X3 parser and minor cleanups
  • Comments

    Comments powered by Disqus