【问题标题】:Boost program_options: allow undeclared from environmentBoost program_options:允许未从环境中声明
【发布时间】:2019-04-16 12:52:53
【问题描述】:

我有一个分两步加载选项的应用程序。在第二步中,options_description 对象中可能未声明某些选项(取决于第一步中传递了哪些选项)。

似乎没有忽略未声明的选项,类似于用于解析 command line argumentsconfiguration files 的选项。

一个最小的工作示例:

#include <boost/program_options.hpp>

namespace po = boost::program_options;

int main() {
  int opt1;

  po::options_description options("my app options");
  options.add_options()
    ("opt1", po::value<int>(&opt1)->default_value(0), "option 1");

  po::variables_map env;
  po::store(po::parse_environment(options, "MYAPP_"), env);
  po::notify(env);

  printf("opt1: %d\n", opt1);
  return 0;
}

默认情况下,您会得到一个零值,正如预期的那样:

$ ./a.out
opt1: 0

如果您设置MYAPP_OPT1,它也可以按预期工作

$ MYAPP_OPT1=123 ./a.out
opt1: 123

但是,如果你设置了一个没有在配置文件中指定的变量,它就会崩溃。

$ MYAPP_UNDEFINED=456 ./a.out
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::program_options::unknown_option> >'
  what():  unrecognised option
Aborted (core dumped)

旁注

还有一件烦人的事情——如果我不声明"opt1",而是声明"OPT1",它甚至不会识别MYAPP_OPT1

【问题讨论】:

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


    【解决方案1】:

    恕我直言,这将是对 boost 库的一个很好的补充,使其与命令行和配置文件解析器相当。

    以下内容改编自my gist


    当使用 Boost 的 program_options 加载环境变量时,无法告诉 boost 忽略那些未在 options_description 对象中指定的变量。

    此 sn-p 显示如何获得与命令行和配置文件解析器可用的 allow_unregistered() 选项类似的行为。

    例如,如果您尝试通过指定名为one 的选项并在parse_environment 中使用前缀MYAPP 来读取MYAPP_ONE,它将正常工作。

    如果options_description 对象中未包含另一个MYAPP_X,则会出现问题。然后会抛出异常。

    如果您使用程序参数(argcargv)或配置文件,库中有一个选项可以简单地忽略未在 options_description 中声明的选项。

    对于环境变量,情况并非如此。这个 sn-p 将简单地读取您声明的选项,并忽略可能已声明的任何其他选项。

    因此,其行为类似于 allow_unregistered() 功能。

    po::options_description options("My Options");
    lib_options.add_options()
      (
        "MY_VAR",
        po::value<bool>(&my_var)->default_value(false),
        "Dummy boolean test"
      )
    ;
    
    po::variables_map env;
    po::store(po::parse_environment(
      options,
      [options](const std::string& var) {
        return std::any_of(
          options.options().cbegin(),
          options.options().cend(),
          [var](auto opt) { return var == opt->long_name(); }) ? var : "";
    }), env);
    po::notify(env);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多