本文介绍了使用Boost program_options指定级别(例如--verbose)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一些选项有多个级别,例如的冗长。
我希望我的用户选择以下两种等效风格:

  //无参数:verbosity 
my_program -v

//计数'v':verbosity 4
my_program -vv --something_else XYZ -vv

//指定value:verbosity 4
my_program --verbose 3

这与Boost program_options库?

解决方案

这是我设想的代码正在使用。


  1. 我们使用 level_value 代替正常 program_options :: value

  2. pass option_level< CHAR>(your_value)其中 CHAR 是短选项字母, your_value 是可选级别,例如详细资料

  3. $ b
    $ b c> #include< boost / program_options.hpp>
    using namespace boost;
    使用命名空间boost :: program_options;

    int main()
    {
    unsigned verbosity = 0U;
    unsigned something_else = 0U;

    options_description desc(options);
    desc.add_options()
    (verbose,v,
    level_value(option_level<'v'>(& verbosity)),
    每个附加详细级别)
    (something_else,s,
    value< unsigned>(& something_else);

    return 0;
    }



    行为



     #verbosity = 7 
    test_options -vvvvv --something_else 5 -vv

    #3重写的最后冗长度
    test_options -vvvvv --something_else 5 -v 7 -v 3

    #无参数总是递增:verbosity = 6
    test_options -v 3 --verbose 5 -v



    实施



    我们需要一些东西来保存关卡:

      // ________________________________________________________________________________________ 

    // t_option_level

    // ________________________________________________________________________________
    struct t_option_level {
    public:
    无符号n
    explicit t_option_level(unsigned n_ = 0):n(n _){}
    t_option_level& inc(unsigned by = 1){n + = by; return * this;}
    t_option_level& set(unsigned val){n = val; return * this;}
    };

    template< typename U>
    inline t_option_level * option_level(U * u)
    {return reinterpret_cast< t_option_level *>(u);}

    增加或设置值的逻辑存在于验证器中:

      #include< boost / program_options.hpp> 
    #include< boost / program_options / options_description.hpp>
    // ________________________________________________________________________________________
    //
    //验证
    // ________________________________________________________________________________________________________________________________________
    模板< unsigned SHORT_NAME>
    void validate(boost :: any& v,
    const std :: vector< std :: string>& values,
    t_option_level< SHORT_NAME> * / * target_type * /,int)
    {
    using namespace boost :: program_options;

    //
    //获取当前值
    //
    t_option_level< SHORT_NAME>一世;
    if(!v.empty())
    i = boost :: any_cast< t_option_level< SHORT_NAME>>(v);

    //
    //提取任何参数
    //
    const std :: string& s = validators :: get_single_string(values,true);
    if(s.empty())
    {
    v = boost :: any(i.inc());
    return;
    }

    char short_name = SHORT_NAME;
    // multiple'values's
    if(s == std :: string(s.length(),short_name))
    {
    v = boost :: any(i.inc (s.length()+ 1));
    return;
    }

    //匹配号
    boost :: regex r(^(\\d +)$);

    //执行regex匹配并将有趣的部分转换为
    // int。
    boost :: smatch what;
    if(regex_match(s,what,r))
    {
    v = boost :: any(i.set(boost :: lexical_cast< unsigned>(s)));
    return;
    }
    else
    {
    throw validation_error(validation_error :: invalid_option_value,\+ s +\不是有效的参数。
    }

    }

    c> program_options :: value_semantic 覆盖以允许零个或一个参数:

      class charT = char> 
    class t_level_value:public boost :: program_options :: typed_value< T,charT>
    {
    public:
    / ** Ctor。 'store_to'参数告知
    存储在何处,当值已知时。参数可以为NULL。 * /
    t_level_value(T * store_to)
    :boost :: program_options :: typed_value< T,charT>(store_to)
    {}
    unsigned min_tokens()const
    {
    return 0;
    }

    unsigned max_tokens()const
    {
    return 1;
    }
    };

    template< class T>
    t_level_value< T> *
    level_value(T * v)
    {
    return new t_level_value&
    }


    Some of my options have multiple levels, e.g. of "verbosity".I would like my users to choose between the following two equivalent styles:

    // no argument: verbosity of 1
    my_program -v
    
    // count the 'v's: verbosity of 4
    my_program -vv --something_else XYZ -vv
    
    // specify the value: verbosity of 4
    my_program --verbose 3
    

    What is the easiest way of doing this with the Boost program_options library?

    解决方案

    This is how I envisage the code being used.

    1. We use level_value in place of the normal program_options::value
    2. pass option_level<CHAR>(your_value) where CHAR is the short option letter, and your_value is the optional level, e.g. verbosity, being supplied

    Example

    #include <boost/program_options.hpp>
    using namespace boost;
    using namespace boost::program_options;
    
    int main()
    {
        unsigned verbosity      = 0U;
        unsigned something_else = 0U;
    
        options_description desc("options");
        desc.add_options()
            ("verbose,v",
                level_value(option_level<'v'>(&verbosity)),
                "Print more verbose messages at each additional verbosity level.")
            ("something_else,s",
                value<unsigned>(&something_else);
    
        return 0;
    }
    

    Behavior

    # verbosity = 7
    test_options -vvvvv --something_else 5 -vv
    
    # final verbosity of 3 overrides
    test_options -vvvvv --something_else 5 -v 7 -v 3
    
    # no argument always increments: verbosity = 6
    test_options -v 3 --verbose 5 -v
    

    Implementation

    We need something to hold the level:

    //________________________________________________________________________________________
    
    //  t_option_level
    
    //________________________________________________________________________________________
    struct t_option_level {
    public:
        unsigned n;
        explicit t_option_level(unsigned n_ = 0):n(n_){}
        t_option_level& inc(unsigned by = 1){n += by; return *this;}
        t_option_level& set(unsigned val){n = val; return *this;}
    };
    
    template <typename U>
    inline t_option_level* option_level(U* u)
    {return reinterpret_cast<t_option_level*>(u);}
    

    The logic to increment or set the value lives in the validator:

    #include <boost/program_options.hpp>
    #include <boost/program_options/options_description.hpp>
    //________________________________________________________________________________________
    //
    //      validate
    //________________________________________________________________________________________
    template <unsigned SHORT_NAME>
    void validate(boost::any& v,
                  const std::vector<std::string>& values,
                  t_option_level<SHORT_NAME>* /*target_type*/, int)
    {
        using namespace boost::program_options;
    
        //
        // Get the current value
        //
        t_option_level<SHORT_NAME> i;
        if (!v.empty())
            i = boost::any_cast<t_option_level<SHORT_NAME>>(v);
    
        //
        //  Extract any arguments
        //
        const std::string& s = validators::get_single_string(values, true);
        if (s.empty())
        {
            v = boost::any(i.inc());
            return;
        }
    
        char short_name = SHORT_NAME;
        // multiple 'values's
        if (s == std::string(s.length(), short_name))
        {
            v = boost::any(i.inc(s.length() + 1));
            return;
        }
    
        // match number
        boost::regex r("^(\\d+)$");
    
        // Do regex match and convert the interesting part to
        // int.
        boost::smatch what;
        if (regex_match(s, what, r))
        {
            v = boost::any(i.set(boost::lexical_cast<unsigned>(s)));
            return;
        }
        else
        {
            throw validation_error(validation_error::invalid_option_value, "\"" + s + "\" is not a valid argument.");
        }
    
    }
    

    This provides the program_options::value_semantic override to allow zero or one arguments:

    template<class T, class charT = char>
    class t_level_value : public boost::program_options::typed_value<T, charT>
    {
    public:
        /** Ctor. The 'store_to' parameter tells where to store
            the value when it's known. The parameter can be NULL. */
        t_level_value(T* store_to)
            : boost::program_options::typed_value<T, charT>(store_to)
        {}
        unsigned min_tokens() const
        {
            return 0;
        }
    
        unsigned max_tokens() const
        {
            return 1;
        }
    };
    
    template<class T>
    t_level_value<T>*
    level_value(T* v)
    {
        return new t_level_value<T>(v);
    }
    

    这篇关于使用Boost program_options指定级别(例如--verbose)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 03:01