7

I am using boost::program_options to handle command line parameters to a program. In the program below I would like group algo, exchanges and admin_port together such that they should all be provided else an exception is thrown (i.e. the don't make sense unless they are together).

I'd also like to print them out in a manner which makes it obvious they are a group.

How would this best be achieved?

#include <boost/program_options.hpp>
#include <cassert>
#include <iostream>
#include <string>

namespace prog_opts = boost::program_options;

int main(int argc, char *argv[])
{
    int rc = 0;

    prog_opts::options_description desc("Usage");
    desc.add_options()
        ("algo", prog_opts::value<std::string>(), "Name of the algo to run")
        ("exchanges", prog_opts::value< std::vector<std::string> >(), "Name(s) of the exchanges which will be available for use")
        ("admin_port", prog_opts::value<unsigned>(), "Admin port on which admin requests will be listened for")
        ("version", "Show version information")
        ("help", "Show help information");

    prog_opts::variables_map args;

    try
    {
        prog_opts::store(prog_opts::parse_command_line(argc, argv, desc), args);
        prog_opts::notify(args);

        if(args.count("algo") && args.count("exchanges") && args.count("admin_port"))
        {
            //TODO:
        }
        else if(args.count("version"))
        {
            //TODO:
        }
        else if(args.count("help"))
        {
            std::cout << desc << std::endl;
        }
        else
        {
            std::cerr << desc << std::endl;
            rc = 1;
        }  
    }
    catch(const prog_opts::error& e)
    {
        std::cerr << "Failed start with given command line arguments: " << e.what() << std::endl;
        rc = 1;
    }

    return rc;
}  
Graeme
  • 4,514
  • 5
  • 43
  • 71

2 Answers2

1

To create mandatory groups you can do that with

prog_opts::value<std::string>()->required()

in the option description part of your program. This would look something like that:

#include <boost/program_options.hpp>
#include <cassert>
#include <iostream>
#include <string>

namespace prog_opts = boost::program_options;

int main(int argc, char *argv[])
{
int rc = 0;

prog_opts::options_description desc("Usage");
desc.add_options()
    ("algo", prog_opts::value<std::string>()->required(), "Name of the algo to run")
    ("exchanges", prog_opts::value< std::vector<std::string> >()->required(), "Name(s) of the exchanges which will be available for use")
    ("admin_port", prog_opts::value<unsigned>()->required(), "Admin port on which admin requests will be listened for")
    ("version", "Show version information")
    ("help", "Show help information");

prog_opts::variables_map args;

try
{
    prog_opts::store(prog_opts::parse_command_line(argc, argv, desc), args);
    prog_opts::notify(args);

    if(args.count("algo") && args.count("exchanges") && args.count("admin_port"))
    {
        //TODO:
    }
    else if(args.count("version"))
    {
        //TODO:
    }
    else if(args.count("help"))
    {
        std::cout << desc << std::endl;
    }
    else
    {
        std::cerr << desc << std::endl;
        rc = 1;
    }  
}
catch(const prog_opts::error& e)
{
    std::cerr << "Failed start with given command line arguments: " << e.what() << std::endl;
    rc = 1;
}

return rc;
}

I would suggest you check out the boost documentation in detail: http://www.boost.org/doc/libs/1_32_0/doc/html/program_options/overview.html#id548509

Also for more complicated argument dependencies it might make sense to "group" them together, creating several option descriptions. http://www.boost.org/doc/libs/1_32_0/doc/html/program_options/howto.html#id549397

  • I'm looking for something similar. This solution works for the given question with the limitation of a single mandatory group. If several groups are needed then the groups must be created manually. – cbuchart Feb 27 '17 at 23:26
0

I would implement that "manually" by something like the following. I am unaware of any capability that Boost provides for doing this otherwise.

unsigned int requiredArgsGroupCount = args.count("algo") + args.count("exchanges") + args.count("admin_port");
if ( (requiredArgsGroupCount > 0) && (requiredArgsGroupCount < 3) )
{
    // Indicate that all three arguments must be specified
}

Just indicate in the argument description text that all three are required if one is specified.

ScoPi
  • 1,193
  • 9
  • 14