Я разместил следующий вопрос на SO, но, думаю boost::program_options
, не могу мне здесь помочь:
У меня есть варианты
--foo
(краткая форма-f
)--bar
, которые требуют особого отношения, они повторяемы, и порядок должен иметь значение. Итак, для следующего:program --foo 1 --z -f 2 --bar 3 --x --foo 4
Я хотел бы составить карту ключевого значения, которая может построить
[("foo", 1), ("foo", 2), ("bar", 3), ("foo", 4)]
.Обратите внимание на порядок этого массива кортежей, он такой же, как и в командной строке. Я отбросил неважные параметры в массиве, но тем не менее они могут присутствовать в командной строке.
Кажется, единственный способ разрешить повторяющиеся параметры с помощью
boost::program_options
вызоваcomposing()
любого заданного параметра, но затем, поскольку каждый из них будет хранить все свои значения в векторе, я теряю порядок, который мне нужен для чередования параметров.Так может
boost::program_options
помочь с этим?
источник: https://stackoverflow.com/questions/36973114/
Я ищу библиотеку, которая позволяет мне перемещаться по проанализированным параметрам (если возможно, с их именами, нормализованными к их длинным или коротким именам) в порядке, указанном в командной строке, потому что такой порядок важен для меня.
Используя последний мастер в CLI11 (будет в версии 1.1) (теперь и официальный пример):
#include <CLI/CLI.hpp>
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
int main(int argc, char **argv) {
CLI::App app;
std::vector<int> foos;
auto foo = app.add_option("--foo,-f", foos);
std::vector<int> bars;
auto bar = app.add_option("--bar", bars);
app.add_flag("--z,--x"); // Random other flags
try {
app.parse(argc, argv);
} catch(const CLI::ParseError &e) {
return app.exit(e);
}
// I perfer using the back and popping
std::reverse(std::begin(foos), std::end(foos));
std::reverse(std::begin(bars), std::end(bars));
std::vector<std::pair<std::string, int>> keyval;
for(auto option : app.parse_order()) {
if(option == foo) {
keyval.emplace_back("foo", foos.back());
foos.pop_back();
}
if(option == bar) {
keyval.emplace_back("bar", bars.back());
bars.pop_back();
}
}
// Prove the vector is correct
for(auto &pair : keyval) {
std::cout << pair.first << " : " << pair.second << std::endl;
}
}
Вывод:
./examples/inter_argument_order --foo 1 --z -f 2 --bar 3 --x --foo 4
foo : 1
foo : 2
bar : 3
foo : 4
Использование Poco, который вызывает обратный вызов для каждого флага, по порядку:
#include <iostream>
#include <Poco/Util/Option.h>
#include <Poco/Util/OptionSet.h>
#include <Poco/Util/Application.h>
#include <Poco/Util/HelpFormatter.h>
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::Application;
using Poco::Util::HelpFormatter;
using Poco::Util::OptionCallback;
struct SampleApp : Application {
void defineOptions(OptionSet &options) {
Application::defineOptions(options);
options.addOption(Option("help", "h", "display help information")
.required(false)
.repeatable(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleHelp)));
options.addOption(Option("foo", "f", "foo option")
.required(false)
.repeatable(true)
.argument("<foo>")
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("bar", "b", "bar option")
.required(false)
.repeatable(false)
.argument("<bar>")
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("z", "", "z option")
.required(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("x", "", "x option")
.required(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
}
void handleHelp(const std::string &, const std::string &) {
helpRequested = true;
displayHelp();
stopOptionsProcessing();
}
void handleOptions(const std::string &name, const std::string &value) {
std::cout << name << " " << value << std::endl;
}
void displayHelp() {
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("<options>");
helpFormatter.setHeader("Foo/Bar options.");
helpFormatter.format(std::cout);
}
bool helpRequested = false;
};
POCO_APP_MAIN(SampleApp)
❯❯❯ ./sample --help
usage: sample <options>
Foo/Bar options.
-h, --help display help information
-f<foo>, --foo=<foo> foo option
-b<bar>, --bar=<bar> bar option
--z z option
--x x option
❯❯❯ ./sample --foo 1 --z -f 2 --bar 3 --x --foo 4
foo 1
z
foo 2
bar 3
x
foo 4
айнпоклум
program_options
может дать вам все, что не было проанализировано как файлvector<string>
. На самом деле, я использую этот уродливый фрагмент кода , чтобы поместить его в карту ключ-значение в проекте, над которым я работаю, и, я думаю, нетрудно адаптировать его к тому, что вам нужно.айнпоклум
boost::program_options::collect_unrecognized()
. Хотя я скажу, что вам, вероятно, не следует предполагать порядок параметров командной строки, т.е. проблема больше в том, что вы пытаетесь сделать это IMO.облитум
matrix_product_program --matrix="{...}" --matrix="{...}" --matrix="{...}"
. Есть ли проблемы с необходимостью подогнать эту ситуацию под решение, как объяснено?айнпоклум
boost::program_options
интересное.облитум
облитум
облитум
collect_unrecognized
и фрагмент, который вы отправили .... Это выглядит не очень хорошо, как я ожидал. Обратите внимание, что я даже упоминаю о получении нормализованных (подразумевающих, что они были распознаны) имен опций в сочетании с соответствующими значениями.айнпоклум