парсинг пользовательских объектов через конфигурационный файл / командную строку, используя параметры программы Boost

Поэтому я только начал добавлять поддержку опций в свой код. Я могу сделать это сам или использовать параметры программы Boost. Единственное, что удерживает меня от использования boost, — это еще одна зависимость, которую я добавляю в проект. Однако, если он может легко обрабатывать сложные объекты, я больше готов заплатить цену.

Я только что попробовал что-то подобное на основе примеров, и это не работает:

#include <boost/program_options.hpp>
namespace po = boost::program_options;#include <iostream>
#include <fstream>
#include <iterator>
using namespace std;struct Grid{
double xmin, xmax;
};

int main(int ac, char* av[])
{
try {
Grid g;

po::options_description cmd("Allowed options");
cmd.add_options()
("help", "produce help message")
("Grid", "grid information")
;

po::variables_map vm;
store(parse_command_line(ac, av, cmd), vm);
notify(vm);

if (vm.count("help")) {
cout << cmd << "\n";
return 0;
}

g = vm["Grid"].as<Grid>();
cout << g.xmin << " " << g.xmax << endl;

}
catch(exception& e)
{
cout << e.what() << "\n";
return 1;
}
return 0;

Когда я запускаю код с ./a.out --Grid {-1, 1}, Я получил boost::bad_any_cast: failed conversion using boost::any_cast, Я не понимаю, что это значит, но я думаю, что я не могу правильно определить повышение типа моего объекта Grid, Как я могу сделать это правильно с Boost?

1

Решение

Во-первых, простой способ заключается в использовании po::value<std::vector<double>>()->multitoken(),:
Тем не менее, вам нужно передать аргументы, как это: --Grid -1 1

int main(int ac, char* av[])
{
try {

po::options_description cmd("Allowed options");
cmd.add_options()
("help", "produce help message")
("Grid", po::value<std::vector<double>>()->multitoken(),
"grid information")
;
po::variables_map vm;
store(parse_command_line(ac, av, cmd), vm);
notify(vm);

if (vm.count("help")) {
cout << cmd << "\n";
return 0;
}

Grid g{vm["Grid"].as<std::vector<double>>()[0],
vm["Grid"].as<std::vector<double>>()[1]};
cout << g.xmin << " " << g.xmax << endl;

}
catch(exception& e)
{
cout << e.what() << "\n";
return 1;
}
}

Если вы хотите передать аргументы, такие как --Grid {-1,1}Вы можете добавить operator>> и разобрать std::string сам:

std::istream& operator>>(std::istream &in, Grid &g)
{
// Note that this code does not do any error checking, etc.
// It is made simple on purpose to use as an example
// A real program would be much more robust than this
std::string line;
std::getline(in, line);
std::stringstream ss(line);
char bracket, comma;
double xmin, xmax;
ss >> bracket >> xmin >> comma >> xmax;
g = Grid{xmin, xmax};
return in;
}

//...
Grid g;
try {

//...
cmd.add_options()
("help", "produce help message")
("Grid", po::value(&g), "grid information")
;
//...

cout << g.xmin << " " << g.xmax << endl;

Кроме того, обратите внимание, что в --Grid {-1,1}, есть нет места: -1,1не -1, 1, Это потому что line будет содержать только {-1,,

Если вы хотите место, вот пример, который может разобрать --Grid {-1, 1}, используя пользовательский валидатор а также multitoken:

// Showing only changes, rest of the code is the same
void validate(boost::any& v, const std::vector<std::string>& val,
Grid*, double)
{
std::stringstream ss(val[0]);
char bracket;
double xmin, xmax;
ss >> bracket >> xmin;
ss.str(val[1]);
ss >> xmax;
v = Grid{xmin, xmax};
}

po::options_description cmd("Allowed options");
cmd.add_options()
("help", "produce help message")
("Grid", po::value(&g)->multitoken(), "grid information")
;
4

Другие решения

Других решений пока нет …