【问题标题】:boost::program_options bool_switch used multiple timesboost::program_options bool_switch 多次使用
【发布时间】:2019-01-14 08:01:57
【问题描述】:

我目前拥有的是

("someOption,s", po::bool_switch(&variable)->default_value(false), "")

我希望能够多次指定参数,每次出现都会切换这个布尔值。

例子:

default value = false

./program -s
value == true

./program -s -s
value == false

./program -s -s -s
value == true

有没有办法多次使用 bool_switch 之类的东西,以便反复打开/关闭?我需要我的自定义类型和验证器吗?

也许我可以以某种方式允许多次指定选项,然后执行 vm.count("someOption") 并根据其值(偶数/奇数)切换我的变量。但我更愿意在选项描述 (add_options) 中指定该行为,而无需稍后检查和修改值。

【问题讨论】:

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


    【解决方案1】:

    我确实花了 70 分钟试图让它工作使用

    • composing() 允许重复
    • 带有implicit_value({}, "")custom 通知器的向量值虚拟选项(它们只运行一次)
    • 自定义notifier() - 无论选项出现和成功解析的频率如何,它们只运行一次
    • store/notify 之后从variables_map 获取向量值选项的大小。可悲的是,大小始终为 1,大概是因为“组合”实际上并没有在单个存储操作中组合(它只在多次运行之间组合,所以不同的选项来源,然后呢?)。

    可悲的结论是,似乎没有办法。在这里,我一贯的口头禅得到了证实:“简单胜过全知设计”,我建议您也这样做,但使用https://github.com/adishavit/argh

    Live On Coliru

    #include "argh.h"
    #include <iostream>
    
    namespace {
        template <typename It>
        size_t size(std::pair<It, It> const& range) { return std::distance(range.first, range.second); }
    }
    
    int main(int argc, char** argv) {
        argh::parser p(argc, argv);
    
        auto num_s = size(p.flags().equal_range("s"));
        bool const variable = num_s % 2;
        std::cout << "Repeated: " << num_s << ", effective " << std::boolalpha << variable;
    
        std::cout << " (Command line was:";
        while (*argv) std::cout << " " << *argv++;
        std::cout << ")\n";
    }
    

    当使用各种命令行运行时,打印:

    Repeated: 0, effective false (Command line was: ../build/sotest)
    Repeated: 1, effective true (Command line was: ../build/sotest -s)
    Repeated: 2, effective false (Command line was: ../build/sotest -s -s)
    Repeated: 3, effective true (Command line was: ../build/sotest -s -s -s)
    Repeated: 4, effective false (Command line was: ../build/sotest -s -s -s -s)
    Repeated: 3, effective true (Command line was: ../build/sotest -s -s -s --other bogus)
    

    【讨论】:

    • 非常感谢您,我很抱歉您的 70 分钟 ;-) 我必须继续使用 boost,因为我们正在将此选项库用于其他“更复杂”的事情。与此同时,我也试图更深入地研究它,目前取得了一些意想不到的小进展。我可以使用 zero_tokens()、我的自定义结构类型和自定义验证函数的组合来允许多个“-s”并计算重复次数,然后我可以将我的结构的一些重新类型添加到 bool 或类似的东西,它会工作。但它看起来很复杂,但也许只有这样......
    • @Martin 祝你好运,如果您有解决方法,请分享您自己的答案。我的position is here on twitter。如果您可以在没有额外假设(例如标志必须是连续的)或丑陋的黑客(如共享全局状态)的情况下使其工作,我会感到惊讶(这再次取决于对解析器实现细节的假设)
    • 如果我成功了我会分享的。
    • 我添加了一些“解决方法”。请随时检查并让我知道您的想法。还缺少一些东西,看起来太复杂了,但也许可以。
    • 我想你应该把它作为答案发布
    【解决方案2】:

    所以这是迄今为止我所获得的最接近的结果。它看起来不是很优雅,更像是一种解决方法,我很乐意知道更好(“更短”)的解决方案。代码也可能有问题,请随时纠正我。 目前,它仅在将默认值视为 false 时才有效。我不知道如何从 true 开始,它需要在 validate 函数中以某种方式知道默认值。 它超出了这个问题的范围,希望在这里得到解决:boost::program_options custom validate and default value

    // my custom class
    class BoolOption {
    public:
        BoolOption(bool initialState = false) : state(initialState) {}
        bool getState() const {return state;}
        void switchState() {state = !state;}
    private:
        bool state;
    };
    
    // two variables
    BoolOption test1;
    BoolOption test2;
    
    // validate
    void validate(boost::any &v, std::vector<std::string> const &xs, BoolOption*, long)
    {
        if (v.empty()) {
            v = BoolOption(true); // I don't know how to assign default here so this works only when default is false
        } else {
            boost::any_cast<BoolOption&>(v).switchState();
        }
    }
    
    optionsDescription->add_options()
            ("test1,t", po::value<BoolOption>(&test1)->default_value(BoolOption(true), "true")->zero_tokens(), "")
            ("test2,T", po::value<BoolOption>(&test2)->default_value(BoolOption(false), "false")->zero_tokens(), "")
    ;
    
    // output result
    cout << test1.getState() << endl;
    cout << test2.getState() << endl;
    

    这似乎工作正常,我可以用某种方式调用它:

    ./program -t -t -T -t -T

    它会切换参数。

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-02
      相关资源
      最近更新 更多