1

is it possible to parse multiple mulit-token parameters with the same name?

Like: program.exe --param a b c --param foo bar ?

I only could get it to work like this: program.exe --param "a b c" --param "foo bar" but then I have to split the parameter myself.

[...]
options.add_options()("param", po::value<vector<string>>()->multitoken()               
    , "description")
[...]

thanks for any hints

pettersson
  • 317
  • 2
  • 10
  • Why don't you show the code that you used? It's a bit ... I dunno to claim "I could get it to work like this", but then *not* share it. It burdens any answerers with redoing all that work for you? – sehe Nov 20 '22 at 20:07
  • Sorry, I forgot to paste the code :/ – pettersson Nov 21 '22 at 05:26

1 Answers1

1

I think you want a combination of composing and multi-token:

Live On Coliru

#include <boost/program_options.hpp>
#include <fmt/ranges.h>
namespace po = boost::program_options;
using strings = std::vector<std::string>;

int main(int argc, char** argv) {
    po::options_description opts;
    opts.add_options()("param",
                       po::value<strings>()
                           ->multitoken()
                           ->composing()
                           ->default_value({}, "")
                           ->implicit_value({}, ""),
                       "you know the drill");

    po::variables_map vm;
    store(parse_command_line(argc, argv, opts), vm);

    if (vm.contains("param")) {
        fmt::print("Params: {}\n", vm["param"].as<strings>());
    }
}

Which prints e.g.:

+ ./a.out
Params: []
+ ./a.out --param
Params: []
+ ./a.out --param a b
Params: ["a", "b"]
+ ./a.out --param a b --param c d
Params: ["a", "b", "c", "d"]

Note, if you don't want to allow --param without a value, remove the implicit_value: Live On Coliru

UPDATE

To the comment:

You can always use the parser section of the library, inspecting the parsed_options instance:

// using parsed-options to see "source" material:
auto parsed = parse_command_line(argc, argv, opts);
for (auto& po : parsed.options) {
    auto key = po.position_key == -1 //
        ? po.string_key
        : '#' + std::to_string(po.position_key);

    fmt::print("Option {}: {}\n", key, po.value);
}

// original logic:
store(parsed, vm);

if (vm.contains("param")) {
    fmt::print("Effective combined params: {}\n", vm["param"].as<strings>());
}

See it Live On Coliru, printing:

+ ./a.out
Effective combined params: []
+ ./a.out --param
Option param: []
Effective combined params: []
+ ./a.out --param a b
Option param: ["a", "b"]
Effective combined params: ["a", "b"]
+ ./a.out --param a b --param c d
Option param: ["a", "b"]
Option param: ["c", "d"]
Effective combined params: ["a", "b", "c", "d"]
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Hi, thanks for the hint. I think I not not have been clear enough, sorry about that. This way I get all the "param" tokens but I cannot distinguish which where the first param and the second. – pettersson Nov 21 '22 at 05:31
  • That's the whole purpose of the library, and specifically `variable_map`: it allows you to consume option values regardless of the source (it can be from a config file, a command line or several at the same time). See e.g. https://stackoverflow.com/a/72807837/85371, https://stackoverflow.com/a/70102829/85371 and this one that contains a little more background about the library's design: https://stackoverflow.com/a/62433436/85371 – sehe Nov 21 '22 at 13:26
  • You can always use the parser section of the library, inspecting the `parsed_options` instance: added a demo also **[Live On Coliru](http://coliru.stacked-crooked.com/a/8d8541f05aa1fae2)** to the answer. – sehe Nov 21 '22 at 13:37
  • 1
    Ah, that's what I was looking for. Thanks for the tip and the links :) – pettersson Nov 21 '22 at 15:18