Boost program_options: 允许未声明的环境
Boost program_options: allow undeclared from environment
我有一个分两步加载选项的应用程序。在第二步中,某些选项可能未在 options_description
对象中声明(取决于第一步中传递的选项)。
似乎没有忽略未声明的选项,类似于解析command line arguments and configuration 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
!
恕我直言,这将是对 boost 库的一个很好的补充,使其与命令行和配置文件解析器保持一致。
以下改编自my gist.
当使用 Boost 的 program_options 加载环境变量时,无法告诉 boost 忽略那些未在 options_description
对象中指定的变量。
此代码段展示了如何获得与可用于命令行和配置文件解析器的 allow_unregistered()
选项类似的行为。
例如,如果您尝试通过指定名为 one
的选项并在 parse_environment
中使用前缀 MYAPP
来读取 MYAPP_ONE
,它将正常工作。
如果 options_description
对象中没有包含另一个 MYAPP_X
,就会出现问题。然后会抛出异常。
如果您使用程序参数(argc
、argv
)或配置文件,库中有一个选项可以简单地忽略未在 options_description
.
对于环境变量,情况并非如此。此代码段将只读取您声明的选项,并忽略可能已声明的任何其他选项。
因此,表现得像 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);
我有一个分两步加载选项的应用程序。在第二步中,某些选项可能未在 options_description
对象中声明(取决于第一步中传递的选项)。
似乎没有忽略未声明的选项,类似于解析command line arguments and configuration 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
!
恕我直言,这将是对 boost 库的一个很好的补充,使其与命令行和配置文件解析器保持一致。
以下改编自my gist.
当使用 Boost 的 program_options 加载环境变量时,无法告诉 boost 忽略那些未在 options_description
对象中指定的变量。
此代码段展示了如何获得与可用于命令行和配置文件解析器的 allow_unregistered()
选项类似的行为。
例如,如果您尝试通过指定名为 one
的选项并在 parse_environment
中使用前缀 MYAPP
来读取 MYAPP_ONE
,它将正常工作。
如果 options_description
对象中没有包含另一个 MYAPP_X
,就会出现问题。然后会抛出异常。
如果您使用程序参数(argc
、argv
)或配置文件,库中有一个选项可以简单地忽略未在 options_description
.
对于环境变量,情况并非如此。此代码段将只读取您声明的选项,并忽略可能已声明的任何其他选项。
因此,表现得像 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);