【问题标题】:Boost program options allowed set of input valuesBoost 程序选项允许输入值集
【发布时间】:2023-03-14 06:29:01
【问题描述】:

有没有办法为参数设置一组允许的输入变量?例如参数“arg”只能有“cat”和“dog”之类的字符串值。

【问题讨论】:

    标签: c++ boost-program-options


    【解决方案1】:

    您可以使用custom validator 功能。为您的选项定义一个不同的类型,然后在该类型上重载 validate 函数。

    struct catdog {
      catdog(std::string const& val):
        value(val)
      { }
      std::string value;
    };
    
    void validate(boost::any& v, 
                  std::vector<std::string> const& values,
                  catdog* /* target_type */,
                  int)
    {
      using namespace boost::program_options;
    
      // Make sure no previous assignment to 'v' was made.
      validators::check_first_occurrence(v);
    
      // Extract the first string from 'values'. If there is more than
      // one string, it's an error, and exception will be thrown.
      std::string const& s = validators::get_single_string(values);
    
      if (s == "cat" || s == "dog") {
        v = boost::any(catdog(s));
      } else {
        throw validation_error(validation_error::invalid_option_value);
      }
    }
    

    该代码引发的异常与任何其他无效选项值引发的异常没有什么不同,因此您应该已经准备好处理它们。

    在定义选项时,请使用特殊选项类型,而不仅仅是 string

    desc.add_options()
      ("help", "produce help message")
      ("arg", po::value<catdog>(), "set animal type")
    ;
    

    我写了一个live example demonstrating use of this code

    【讨论】:

    • 此示例看起来与official documentation 中提供的示例非常相似。但是,你也需要实现一个提取操作符函数std::istream &amp;operator&gt;&gt;(std::istream &amp;in, catdog &amp;cd){return in &gt;&gt; in.value;}`
    • 是的,@Russoue,我的代码直接改编自我之前链接到的文档。不过,我不知道您为什么认为代码需要流提取。我已经包含了一个伪造您的主张的工作示例。该文档使用lexical_cast 将输入字符串转换为所需的数据类型,如果您想使用相同的技术,那么您确实需要实现operator&gt;&gt;。不过,我的示例使用直接构造。 如何从字符串创建自定义类型超出了这个问题的范围。
    【解决方案2】:

    一个非常简单的方法是将“动物”作为普通字符串,然后通知您测试并在需要时抛出。

    if (vm.count("animal") && (!(animal == "cat" || animal == "dog")))
            throw po::validation_error(po::validation_error::invalid_option_value, "animal");
    

    【讨论】:

    • 这不正是迈克尔建议的吗?
    • @RobKennedy 除了迈克尔说“这是你可以做的”,而乔根说“这是你可以做的,这就是它的样子”
    【解决方案3】:

    我浏览了 Boost.Program_options 文档,但你是否可以做到这一点对我来说并不明显。我的印象是该库主要关注解析命令行,而不是验证它。您可能可以使用custom validator 解决问题,但这涉及在输入错误时引发异常(这可能是比您想要的更严重的错误)。我认为该功能更适合确保您确实得到了一个字符串,而不是它是“猫”或“狗”。

    我能想到的最简单的解决方案是让库正常解析命令行,然后稍后添加您自己的代码来验证--arg 是否设置为catdog。然后你可以打印一个错误并退出,恢复到一些合适的默认值,或者你喜欢的任何东西。

    【讨论】:

      猜你喜欢
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多