Handle no value option in Config file in Boost program_options
在此之前已经有人问过这个问题-Boost parse_config_file,空键值。但是,由于那里没有提供适当的解决方案,因此我再次提出要求,希望有人可以提供更好的解决方案。
与上述问题不同,就我而言,代码未引发Boost错误:
1 | boost::program_options::invalid_option_value |
相反,对于
我还尝试了-在添加选项的同时
UPDATE最初的答案有错误的主意。这是更新。
因此,您希望
这意味着默认值语义(即通知时发生的事情-将状态从解析器组件迁移到存储组件)不是很好。
您可以通过发明自己的价值语义(可以说是mybool_switch)和/或解决
但是,到目前为止,最简单的选择是在解析器阶段进行干预,在您
这是一个带有现场演示的相当完整的插图:
Coliru直播
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <boost/program_options/config.hpp> #include <boost/program_options.hpp> #include <iostream> #include <iomanip> namespace po = boost::program_options; int main() { po::options_description desc; desc.add_options() ("foo", po::bool_switch()) ("bar", po::bool_switch()->default_value(false)) ("qux", po::bool_switch()->implicit_value(false)) ; std::set<std::string> const bool_switches {"foo","bar","qux" }; for (std::string contents : {"","foo=","foo=true", "bar=","bar=true", "qux=","qux=true"}) { std::istringstream iss(contents); po::parsed_options parsed = po::parse_config_file(iss, desc, false); std::cout <<"\ ---\ " << std::quoted(contents) <<"\ "; // the magic is here: for (auto it = parsed.options.begin(); it!= parsed.options.end();) { using V = std::vector<std::string>; V const& v = it->value; if (bool_switches.count(it->string_key) && (v==V{} || v==V{""})) { std::cout <<"*** Discarding config key without a value:" << it->string_key <<"\ "; it = parsed.options.erase(it); } else { ++it; } } po::variables_map vm; po::store(parsed, vm); for (auto& key : bool_switches) { auto& entry = vm[key]; std::cout <<"" << key <<" ->" << std::boolalpha << (entry.empty()?" .empty()":"") << (entry.defaulted()?" .defaulted()":""); if (entry.empty()) std::cout <<" (no value)\ "; else std::cout <<" value:" << entry.as<bool>() <<"\ "; } } } |
将打印哪个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | --- "" bar -> .defaulted() value:false foo -> .defaulted() value:false qux -> .defaulted() value:false --- "foo=" *** Discarding config key without a value: foo bar -> .defaulted() value:false foo -> .defaulted() value:false qux -> .defaulted() value:false --- "foo=true" bar -> .defaulted() value:false foo -> value:true qux -> .defaulted() value:false --- "bar=" *** Discarding config key without a value: bar bar -> .defaulted() value:false foo -> .defaulted() value:false qux -> .defaulted() value:false --- "bar=true" bar -> value:true foo -> .defaulted() value:false qux -> .defaulted() value:false --- "qux=" *** Discarding config key without a value: qux bar -> .defaulted() value:false foo -> .defaulted() value:false qux -> .defaulted() value:false --- "qux=true" bar -> .defaulted() value:false foo -> .defaulted() value:false qux -> value:true |