【问题标题】:Vector arguments in Boost Program OptionsBoost 程序选项中的向量参数
【发布时间】:2011-12-31 19:43:15
【问题描述】:

我有两个相关的问题:

  1. 使用 Boost 程序选项允许传递一系列值的最简单方法是什么?我的目标是避免使用prog --opt 1 --opt 2 --opt 3,而是使用prog --opt 1 2 3

  2. 最简单的方法是有一个选项,即 exactly 两个数字,例如prog --opt 137 42?

(我不需要任何“免费”程序参数。)

【问题讨论】:

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


    【解决方案1】:

    这是一个迟到的答案,但我希望它对某人有所帮助。您可以轻松地在第 1 项中使用相同的技术,但您需要对向量中的项数添加另一个验证:

    来自 rcollyer 的示例:

    namespace po = boost::program_options;
    po::option_descriptions desc("");
    
    desc.add_options()
     ("opt", po::value<std::vector<int> >()->multitoken(), "description");
    
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm); 
    
    vector<int> opts;
    if (!vm["opt"].empty() && (opts = vm["opt"].as<vector<int> >()).size() == 2) {
      // good to go
    }
    

    【讨论】:

    • 如果根据 C++11 标准进行编码,您可以再次删除该空间,它在那里受到官方支持(以及在任何主要编译器中,例如 gcc>=4.6)。 VC 多年来一直将此作为特殊扩展。
    【解决方案2】:

    对于第一部分,这应该可以工作

    namespace po = boost::program_options;
    po::option_descriptions desc("");
    
    desc.add_options()
     ("opt", po::value<std::vector<int> >()->multitoken(), "description");
    

    第二部分,需要更多的工作。函数po::value 返回一个po::typed_value&lt; T, charT &gt;,您必须在其上覆盖多个函数的行为,如下所示

    template< typename T, typename charT = char >
    class fixed_tokens_typed_value : public po::typed_value< T, charT > {
       unsigned _min, _max;
    
       typedef po::typed_value< T, charT > base;
    
     public:
    
       fixed_tokens_typed_value( T * t, unsigned min, unsigned max ) 
         : _min(min), _max(max), base( t ) {
           base::multitoken();
       }
    
       virtual multi_typed_value* min_tokens( unsigned min ) {
           _min = min;
           return *this;
       }
       unsigned min_tokens() const {return _min;}
    
       virtual multi_typed_value* max_tokens( unsigned max ) {
           _max = max;
           return *this;
       }
       unsigned max_tokens() const {return _max;}
    
       base* zero_tokens() {
           _min = _max = 0;
           base::zero_tokens();
           return *this;
       }
    }
    

    需要配上

    template< typename T >
    fixed_tokens_typed_value< T > 
    fixed_tokens_value(unsigned min, unsigned max) {
        return fixed_tokens_typed_value< T >(0, min, max ); }
    
    template< typename T >
    fixed_tokens_typed_value< T > 
    fixed_tokens_value(T * t, unsigned min, unsigned max) {
        fixed_tokens_typed_value< T >* r = new
                       fixed_tokens_typed_value< T >(t, min, max);
        return r; }
    

    然后

    desc.add_options()
     ("opt", po::fixed_tokens_value<std::vector<int> >(2,2), "description");
    

    应该可以。我还没有机会测试它,所以它可能包含一些错误。但是,至少应该让您了解您需要什么。

    【讨论】:

    • @Szabolcs,这段代码的一个有趣点是它默认需要使用向量。否则,您将如何存储这些值?所以,我觉得po::typed_value&lt; T, charT &gt;应该改成po::typed_value&lt; std::vector&lt; T &gt;, charT &gt;
    • 这是否也适用于std::arrays 或std::listss 而不是向量?
    • @einpoklum 我不明白为什么不这样做。但是,我认为std::array 会有点棘手,因为我不知道用于插入容器的内容,尽管这可能是可配置的,并且它的固定大小需要一些调整。相比之下,std::list 没有这些限制,所以我怀疑您可以将其用作替代品。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多