I have a Visual Studio 2008 C++ application using boost v1.45.0 program-options.
I would like to be able to parse a command-line option that looks like this: foo.exe -x 1,2, 4-7
such that it produces a std::vector< int >
with the values [1, 2, 4, 5, 6, 7]. So, I've written a custom validator:
typedef std::vector< int > IDList;
void validate( boost::any& v, const std::vector< std::string >& tokens, IDList*, int )
{
// Never gets here
}
int _tmain( int argc, _TCHAR* argv[] )
{
IDList test_case_ids;
po::options_description desc( "Foo options" );
desc.add_options()
("id,x", po::value< IDList >(), "Specify a single ID or a range of IDs as shown in the following command line: foo.exe -x10,12, 15-20")
;
po::variables_map vm;
try
{
po::store( po::parse_command_line( argc, argv, desc ), vm );
po::notify( vm );
}
catch( const std::exception& e)
{
std::cerr << e.what() << std::endl;
std::cout << desc << std::endl;
return 1;
}
return 0;
}
But, I never get to m开发者_StackOverflow社区y custom validator code. I always get an exception in parse_command_line
with the message: in option 'id': invalid option value
.
What do I need to do to make this work as desired?
Thanks, PaulH
The typedef std::vector<int>
as a boost::program_options::value_semantic
does not work the way you desire because a vector
has a special meaning to the program options library:
The library provides special support for vectors -- it will be possible to specify the option several times, and all specified values will be collected in one vector.
which means a description like so
typedef std::vector< int > IDList;
po::options_description desc( "Foo options" );
desc.add_options()
("id,x", po::value< IDList >(), "list of IDs")
;
is coalesced into a single std::vector<int>
given the following command line
a.out --id 1 --id 2 --id 3 --id 4
the result would be a std::vector
with four elements. You need to define a specific type to use the custom validator, struct IDList
is the correct approach.
You could try writing your own function to parse the command line options:
See here
You write your own parser function, e.g. reg_foo, and use it as follows:
variables_map vm;
store(command_line_parser(argc, argv).options(desc).extra_parser(reg_foo)
.run(), vm);
See also the example code distributed with boost, in example/custom_syntax.cpp
The problem is the definition of IDList
. If I change the definition to match the magic_number
type used in the regex.cpp
sample, it works.
struct IDList
{
public:
std::vector< int > ids_;
IDList( std::vector< int > ids ) : ids_( ids ) {}
};
I haven't investigated why a typedef
is a problem for the framework, but this works.
-PaulH
精彩评论