带有可选参数的 Poco 选项

Poco Option with optional argument

我有一个基于 Poco (v1.9.4) 的 class

class PreprocessingApp : public Poco::Util::Application

使用这两种方法:

void PreprocessingApp::defineOptions(OptionSet& options)
{
    Application::defineOptions(options);

    options.addOption(
        Option("proxy", "p", "Proxify connection")
        .required(false)
        .repeatable(false)
        .argument("the value", false)
        .callback(OptionCallback<PreprocessingApp>(this, &PreprocessingApp::handleBooleanOption))
    );

    options.addOption(
        Option("test", "t", "Test something")
        .required(true)
        .repeatable(false)
        .callback(OptionCallback<PreprocessingApp>(this, &PreprocessingApp::handleBooleanOption))
    );
}

void PreprocessingApp::handleBooleanOption(const string& name, const string& value)
{
    bool actualValue = value.empty() | value == "true" | value == "1";
    config().setBool(name, actualValue);
}

如您所见,“proxy”是一个布尔选项。我添加了 ".argument("the value", false)" 以允许使用此选项传递参数,但将 "required" 标记为 false 以使其成为可选的。
这样我希望允许这个功能:

PreprocessingApp [-p [value]] -t [value]

两种变体都应该有效:

PreprocessingApp -p -t 
PreprocessingApp -p true -t

实际调试handleBooleanOption时,“value”总是空“”。
需要切换为true(.argument("the value", true))时,"value"为"-t",省略下一个option处理。

是否有任何解决方案可以使其按预期工作?

根据 Poco documentation:

Option arguments can be specified in three ways. If a Unix short option ("-o") is given, the argument directly follows the option name, without any delimiting character or space ("-ovalue"). In default option mode, or if a Unix long option ("--option") is given, the option argument is delimited from the option name with either an equal sign ('=') or a colon (':'), as in "--option=value" or "/option:value". Finally, a required option argument can be specified on the command line after the option, delimited with a space, as in "--option value" or "-o value". The latter only works for required option arguments, not optional ones.

基本上,必需参数需要在名称和值之间添加 space,而可选参数则不需要。因此,对于您的可选参数,请像这样指定它:-ptrue--proxytrue--proxy:true.

对于必需的参数,这里还有一个问题。您可能认为使用 setter .required(true)Poco::Util::Option 就足以在代码中定义所需的参数,但显然不是。您还必须使用 setter .argument(),默认情况下将 required 设置为 true:

Option & argument(
    const std::string & name,
    bool required = true
);

因此,将所需参数的代码更改为:

options.addOption(
    Poco::Util::Option("test", "t", "Test something")
        .required(true)
        .repeatable(false)
        .argument("test")
        .callback(Poco::Util::OptionCallback<ModbusInterface>(this, &ModbusInterface::handleBooleanOption))
    );

那么您应该可以像这样调用您的应用程序,例如:

PreprocessingApp -ptrue -t true