Search code examples
c++boostboost-program-options

How to have an optional option value in boost program options?


I am using the Boost program option and I want to offer an option which has three ways:

  1. If not define
  2. If defined but no value
  3. If defined with a value

For example, I have a program that works on a file such as a.jpg, and I want to offer the user to be able to use it in the following scenarios:

myapp.exe a.jpg  : process jpeg 
myapp.exe a.jpg -e : process jpeg and generate report at the same directory as a.jpg
myapp.exe a.jpg -e c:\tmp\ : process jpeg and generate report at c:\tmp\

How can I do this with Boost program options?


Solution

  • You can achieve this effect by giving the value both a default_value and an implicit_value.

    The default_value will be used when the option is not specified at all. The implicit_value will be used when the option is specific without a value. If a value is specified, it will override the default and implicit.

    So, some code to do this could look something like this:

    #include "boost/program_options.hpp"
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main(int argc, char** argv)
    {
        namespace po = boost::program_options;
    
        po::options_description desc("Options");
        desc.add_options()
            ("process-jpeg,e", po::value<string>()->default_value("")->implicit_value("./"), "Processes a JPEG.");
    
        po::variables_map vm;
        try
        {
            po::store(po::parse_command_line(argc, argv, desc), vm);
            po::notify(vm);
        } catch (po::error& e) {
            cerr << "ERROR: " << e.what() << endl << endl << desc << endl;
            return 1;
        }
    
        string outputDir = vm["process-jpeg"].as<string>();
        if (outputDir.empty()) {
            cout << "-e was not provided on the command line" << endl;
        } else {
            cout << "-e is using directory: " << outputDir << endl;
        }
    }
    

    Running this example code prints:

    $ ./jpg_processor
    -e was not provided on the command line
    
    $ ./jpg_processor -e
    -e is using directory: ./
    
    $ ./jpg_processor -e c:\tmp
    -e is using directory: c:\tmp