boost::program_options bool_switch 多次使用

boost::program_options bool_switch used multiple times

我目前拥有的是

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

我希望能够多次指定参数,每次出现都会切换此 bool 的值。

示例:

default value = false

./program -s
value == true

./program -s -s
value == false

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

有没有办法多次使用 bool_switch 之类的东西,然后反复切换 on/off?我需要我的自定义类型和验证器吗?

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

我真的花了 70 分钟尝试使用

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

可悲的结论是,似乎没有办法。在这里,我惯常的口头禅得到了证实:"Simplicity Trumps Omniscient Design",我建议做同样的事情,但使用 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)

这就是我到目前为止的接近程度。它看起来不是很优雅,更像是一种解决方法,我很乐意知道更好的 ("shorter") 解决方案。代码也可能存在一些问题,请随时纠正我。 目前它仅在 default 被视为 false 时才有效。我不知道如何从 true 开始,它需要以某种方式知道验证函数中的默认值。 它超出了这个问题的范围,希望在这里解决:

// 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

它会切换参数。