12

我正在使用 boost program_options 1.50.0

我想为我的程序 foobar 允许以下内容 foobar --debug 2 --debug 3

在 boost program_options 代码中,有一个示例 regex.cpp,它显示了创建新类型并为该类型创建验证器。
我试过了,它可以工作,但现在我不能使用其他一些 add_options() typed_value 选项,比如 default_value、组合等。

这是我到目前为止所尝试的:

    #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 继承的,但我还没有找到这样做的好方法。

4

1 回答 1

10

我认为您不需要使用验证器定义自定义类型来获得所需的结果。它可以通过库现有的语义信息支持来完成。考虑这个例子

#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$ 
于 2013-01-16T22:04:28.447 回答