Reputation: 4602
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;
}
Upvotes: 7
Views: 2137
Reputation: 19
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
Upvotes: 1
Reputation: 1195
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.
Upvotes: 0