Search code examples
c++boostboost-program-options

How to handle unsolicited parameters in boost::program_options


I use boost::program_options to provide command line parsing interface to my application. I would like to configure it to parse the options,

using namespace boost::program_options;
options_description desc("Allowed options");
desc.add_options()
    ("help,h", "produce help message")
    ("version,v", "print the version number")
    ("include-path,I", value< vector<string> >(), "include path")
    ("input-file,i", value<string>(), "input file");

positional_options_description p;
p.add("input-file", 1);

variables_map vm;

parsed_options parsed = command_line_parser(ac, av).
options(desc).positional(p).run();
store(parsed, vm);
notify(vm);

I would like to configure it so that every token after the last switch is returned in a form of vector. I have tried using collect_unrecognized as per example given in Boost documentation but I have ran into some problems because I am also using positional arguments for the input file.

Basically I would like to do it like this. If I have:

./program -i "inputfile.abc" argument1 argument2 argument3

I would like it to store inputfile.abc in the input-file value and return a vector<string> of argument1, argument2 and argument3 as unsolicited arguments.

I would however also like to be able to have a positional argument, so that

./program "inputfile.abc" argument1 argument2 argument3

would give me the same result.

I am sorry if this has already been asked and thank you for help.


Solution

  • I came up with code that does the trick, but it is a slight workaround. That is, I dropped the positional clause and resorted to taking the first argument of the unrecognized ones. It seems to be working fine, but it is not very flexible.

    using namespace boost::program_options;
    
    options_description desc("Allowed options");
    desc.add_options()
        ("help,h", "produce help message")
        ("version,v", "print the version number")
        ("include-path,I", value< vector<string> >(), "include path")
        ("input-file,i", value<string>(), "input file")
        ;
    
    variables_map vm;
    vector<string> additionalParameters;
    
    parsed_options parsed = command_line_parser(ac, av).
        options(desc).allow_unregistered().run();
    store(parsed, vm);
    additionalParameters = collect_unrecognized(parsed.options, 
        include_positional);
    notify(vm);
    
    if (!vm.count("input-file"))
        if (additionalParameters.empty()) 
        {
            cerr << "error: No input file specified\n";
            return EXIT_FAILURE;
        } 
        else
        {
            inputFileName = additionalParameters[0];
            additionalParameters.erase(additionalParameters.begin());
        }
    else
        inputFileName = vm["input-file"].as<string>();