处理Boost程序_options中Config文件中的无值选项。

问题描述 投票:1回答:1

这个问题之前已经有人问过了----。Boost parse_config_file,空键值。. 但由于那里没有提供合适的解决方案,所以我又问这个问题,希望有人能提供更好的解决方案。

与上面的问题不同,在我的案例中,代码没有抛出Boost Error。

boost::program_options::invalid_option_value

相反,对于... string options,它将该值设置为一个 empty string("") 而对于 bool,它被设置为 true. 我的代码的目的是识别配置文件中是否设置了某些选项。我希望用 vm[optionName].count() (其中vm是variables_map对象),但在没有指定值的情况下,如 option=这将返回true,因此不能使用。我也试过- vm[optionName].defaulted() , vm[optionName].empty()implicit_value()default_value() 在添加选项的时候,但没有一个是有效的。

c++ boost boost-program-options
1个回答
1
投票

更新 最初的答案弄错了。下面是更新的内容。

所以你想 foo= (没有值)的行为就好像这行根本不在配置中一样。

这意味着默认的值语义(即通知时发生的事情--将状态从解析器组件迁移到存储组件)并不好。

你可以通过发明你自己的值语义(可以说是mybool_switch)来解决这个问题,也可以通过解决一个 value<my_particulat_bool> 在这里,你可以添加流式操作,使选项的行为方式是你想要的。换句话说,就是用加农炮来射杀一只苍蝇。

然而,到目前为止,更简单的方案是在解析器阶段进行干涉,改变了的 parsed_options 在你 notify().

这里有一个相当完整的插图与现场演示。

Live On Coliru

#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 << "\n---\n" << std::quoted(contents) << "\n";

        // 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 << "\n";
                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)\n";
            else
                std::cout << " value:" << entry.as<bool>() << "\n";
        }
    }
}

这将打印

---
""
 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
© www.soinside.com 2019 - 2024. All rights reserved.