If my command line is:
> prog --mylist=a,b,c
Can Boost's program_options be setup to see three distinct argument values for the mylist
argument? I have configured program_options as:
namespace po = boost::program_options;
po::options_description opts("blah")
opts.add_options()
("mylist", std::vector<std::string>>()->multitoken, "description");
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, opts), vm);
po::notify(vm);
When I check the value of the mylist
argument, I see one value as a,b,c
. I'd like to see three distinct values, split on comma. This works fine if I specify the command line as:
> prog --mylist=a b c
or
> prog --mylist=a --mylist=b --mylist=c
Is there a way to configure program_options so that it sees a,b,c
as three values that should each be inserted into the vector, rather than one?
I am using boost 1.41, g++ 4.5.0 20100520, and have enabled c++0x experimental extensions.
EDIT:
The accepted solution works but ends up being more complicated, IMO, than just iterating through a vector and splitting the values manually. In the end, I took the suggestion from James McNellis and implemented it that way. His solution wasn't submitted as an answer, however, so I accepted the other correct solution from hkaiser. Both worked, but the manual tokenization is clearer.
You could register a custom validator for your option:
namespace po = boost::program_options;
struct mylist_option
{
// values specified with --mylist will be stored here
vector<std::string> values;
// Function which validates additional tokens from command line.
static void
validate(boost::any &v, std::vector<std::string> const &tokens)
{
if (v.empty())
v = boost::any(mylist_option());
mylist_option *p = boost::any_cast<mylist_option>(&v);
BOOST_ASSERT(p);
boost::char_separator<char> sep(",");
BOOST_FOREACH(std::string const& t, tokens)
{
if (t.find(",")) {
// tokenize values and push them back onto p->values
boost::tokenizer<boost::char_separator<char> > tok(t, sep);
std::copy(tok.begin(), tok.end(),
std::back_inserter(p->values));
}
else {
// store value as is
p->values.push_back(t);
}
}
}
};
which then can be used as:
opts.add_options()
("mylist", po::value<mylist_option>()->multitoken(), "description");
and:
if (vm.count("mylist"))
{
// vm["mylist"].as<mylist_option>().values will hold the value specified
// using --mylist
}