我正在使用boost program_options 1.50.0
我想为我的节目foobar提供以下内容
foobar --debug 2 --debug 3
从boost program_options代码中,有一个示例regex.cpp,它显示了创建新类型并为该类型创建验证器。
我试过了,它可以工作,但现在我不能使用其他一些add_options()typed_value选项,比如default_value,composing等。
这是我到目前为止所尝试的内容:
#include <boost/program_options.hpp>
using namespace boost;
using namespace boost::program_options;
#include <iostream>
using namespace std;
struct lastmultioccurrenceint {
public:
lastmultioccurrenceint(int n) : n(n) {}
int n;
};
void validate(boost::any& v,
const std::vector< std::string >& xs,
//const std::vector< std::basic_string<charT> >& xs,
lastmultioccurrenceint* , int)
{
using namespace boost::program_options;
cerr << "IN VALIDATE" << endl;
//validators::check_first_occurrence(v);
string s = validators::get_single_string(xs);
if (!v.empty()) {
cerr << "\tPRINTTING MULTIOCCURENCE WARNING, allowing v to be overwritten" << endl;
cerr << "\tEarlier value was: " << boost::any_cast<int>(v) << endl;
cerr << "\tNew value is: " << s << endl;
}
try {
//v = any(lastmultioccurrenceint(lexical_cast<int>(sx)));
//v = any(lexical_cast<int>(sx)); // works
v = any(lexical_cast<int>(s));
//v = any(lexical_cast<lastmultioccurrenceint>(s));
//v = any(4);
//}
/*catch(const bad_lexical_cast&) {
boost::throw_exception(validation_error::invalid_option_value(s));
} */
}
catch(const bad_lexical_cast&) {
throw validation_error(validation_error::invalid_option_value);
}
cerr << "made it through" << endl;
int main (int argc, char **argv) {
variables_map m_varMap;
// define style
// unix_style = (allow_short | short_allow_adjacent | short_allow_next
// | allow_long | long_allow_adjacent | long_allow_next
// | allow_sticky | allow_guessing
// | allow_dash_for_short),
// ... allows typical unix-style options
// allow_long_disguise = can use "-" instead of "--"
// Reference: http://www.boost.org/doc/libs/1_42_0/doc/html/boost/program_options/command_line_style/style_t.html
//
try {
ProgOpts::command_line_style::style_t style = ProgOpts::command_line_style::style_t(
ProgOpts::command_line_style::unix_style |
//ProgOpts::command_line_style::case_insensitive |
ProgOpts::command_line_style::allow_long_disguise );
options_description options("YDD");
//lastmultioccurrenceint debugOpt;
options.add_options()
("debug", value<lastmultioccurrenceint>(), "debug value (0-4), default is 0 (performance mode)")
//("debug", value<lastmultioccurrenceint>(&debugOpt)->default_value(0)->composing(), "debug value (0-4), default is 0 (performance mode)")
;
//ProgOpts::parsed_options firstPreParsed = ProgOpts::command_line_parser(argc,argv).options(options).style(style).allow_unregistered().run();
ProgOpts::parsed_options firstPreParsed = ProgOpts::command_line_parser(argc,argv).options(options).allow_unregistered().run();
ProgOpts::store(firstPreParsed, m_varMap);
ProgOpts::notify(m_varMap);
}
/*catch (boost::program_options::multiple_occurrences &e) {
cerr << "GOT MULTIPLES" << endl;
cerr << "Option Name: " << e.get_option_name() << endl;
cerr << e.what() << endl;
}
catch(boost::bad_any_cast& e) {
cerr << "WRONG TYPE" << endl;
cerr << e.what() << endl;
} */
catch(std::exception& e) {
cerr << "SOMETHING ELSE" << endl;
cerr << e.what() << endl;
}
catch(...) {
cerr << "UNKNOWN ERROR" << endl;
}
cerr << "DEBUG OPT IS: " << m_varMap["debug"].as<int>() << endl;
}
所以,如果我这样做: foobar --debug 2 --debug 3
如果我注释掉当前的调试选项......
("debug", value<lastmultioccurrenceint>(), "debug value (0-4), default is 0 (performance mode)")
...并取消注释以下两行:
lastmultioccurrenceint debugOpt;
("debug", value<lastmultioccurrenceint>(&debugOpt)->default_value(0)->composing(), "debug value (0-4), default is 0 (performance mode)")
......然后它甚至无法编译。
你知道怎么做才能让我使用default_value和编写吗? 它可能是继承自typed_value,但我还没有找到一个很好的方法来做到这一点。
答案 0 :(得分:7)
我认为您不需要使用验证器定义自定义类型以实现所需的结果。可以使用库的现有语义信息支持来完成。考虑这个例子
#include <boost/assign/list_of.hpp>
#include <boost/program_options.hpp>
#include <boost/version.hpp>
#include <iostream>
int
main( int argc, char** argv )
{
namespace po = boost::program_options;
po::options_description desc("Options");
typedef std::vector<unsigned> DebugValues;
DebugValues debug;
desc.add_options()
("help,h", "produce help message")
("debug", po::value<DebugValues>(&debug)->default_value(boost::assign::list_of(0), "0")->composing(), "set debug level")
;
po::variables_map vm;
try {
const po::positional_options_description p; // note empty positional options
po::store(
po::command_line_parser( argc, argv).
options( desc ).
positional( p ).
run(),
vm
);
po::notify( vm );
if ( vm.count("help") ) {
std::cout << desc << "\n";
std::cout << "boost version: " << BOOST_LIB_VERSION << std::endl;
return 0;
}
} catch ( const boost::program_options::error& e ) {
std::cerr << e.what() << std::endl;
}
std::cout << "got " << debug.size() << " debug values" << std::endl;
if ( !debug.empty() ) {
DebugValues::const_iterator value( debug.end() );
std::advance( value, -1 );
std::cout << "using last value of " << *value << std::endl;
}
}
和样本用法:
samm$ ./a.out -h
Options:
-h [ --help ] produce help message
--debug arg (=0) set debug level
boost version: 1_46_1
samm$ ./a.out --debug 1 --debug 2
got 2 debug values
using last value of 2
samm$ ./a.out --debug 4 --debug 1
got 2 debug values
using last value of 1
samm$ ./a.out --debug 4 --debug 1 --debug 9
got 3 debug values
using last value of 9
samm$