使用Boost program_options指定级别(例如--verbose)

时间:2013-06-13 17:40:16

标签: c++ boost boost-program-options

我的一些选项有多个级别,例如“冗长”。 我希望我的用户在以下两种等效样式中进行选择:

// 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

使用Boost program_options库执行此操作的最简单方法是什么?

1 个答案:

答案 0 :(得分:1)

这就是我设想使用的代码的方式。

  1. 我们使用level_value代替普通program_options::value
  2. 通过option_level<CHAR>(your_value) CHAR是短选项字母,your_value是可选级别,例如冗长,提供
  3. 实施例

    #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;
    }
    

    行为

    # 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
    

    实施

    我们需要一些东西来保持水平:

    //________________________________________________________________________________________
    
    //  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);}
    

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

    #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.");
        }        
    
    }
    

    这提供program_options::value_semantic覆盖以允许零个或一个参数:

    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);
    }