CLI11
CLI11 copied to clipboard
Add modifier to treat options as vectors
The only way to make an option return a vector appears to be via variable assignment to a vector. The subcommands in files example shows use of std::shared_ptr to manage the scope of this variable; however, lambda capture of shared pointers causes a shared pointer cycle.
I've been using auto val = cmd->get_option("val")->as<TYPE>();, capturing only the command into the lambda for other types, but this does not appear to be possible for vector options:
void register_read_cmd(CLI::App& parent) {
auto cmd = parent.add_subcommand("read", "parse input file(s)");
cmd->add_option("input", "file(s) to parse")
->required()
->check(CLI::ExistingFile);
cmd->callback([cmd]() {
auto input_files = cmd->get_option("input")->as<std::vector<std::string>>();
read_cmd(input_files);
});
}
The code above results in The following argument was not expected, quoting the 2nd argument provided.
The shared pointer solution demo'd in the example does work, but of course with the shared pointer cycle issue:
void register_read_cmd(CLI::App& parent) {
auto cmd = parent.add_subcommand("read", "parse input file(s)");
auto input_files = std::make_shared<std::vector<std::string>>();
cmd->add_option("input", *input_files, "file(s) to parse")
->required()
->check(CLI::ExistingFile);
cmd->callback([input_files]() {
read_mqb_cmd(*input_files);
});
}
I would expect that using expected(1, ...) on the option would switch it into "vector mode".
A workaround for managing scope would be to subclass App and use member variables instead, or use static variables.
If you want the first one to think it is a vector then you can
void register_read_cmd(CLI::App& parent) {
auto cmd = parent.add_subcommand("read", "parse input file(s)");
cmd->add_option("input", "file(s) to parse")
->required()
->check(CLI::ExistingFile)
->expected(CLI::details::expected_max_vector_size); //this will trigger any vector like changes
cmd->callback([cmd]() {
auto input_files = cmd->get_option("input")->as<std::vector<std::string>>();
read_cmd(input_files);
});
}
Ah thanks, I saw that option in the Option *expected(int value_min, int value_max) definition too. Looks like the key here is actually allow_extra_args(). This avoids needing to worry about accessing the CLI::detail namespace. Maybe I can update this issue to add some clarity to the docs. Looks like the option does already exist!