使用提升程序选项通过配置文件/命令行解析自定义对象

parse custom objects through config file/command line using boost program options

本文关键字:命令行 对象 自定义 配置文件 程序 选项      更新时间:2023-10-16

所以我刚刚开始向我的代码添加选项支持。我可以自己做,也可以使用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的提升。如何通过提升正确执行此操作?

首先,简单的方法是使用 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")
        ;