提升值的程序选项名称

时间:2015-09-03 13:21:48

标签: c++ boost boost-program-options

我的目标是创建一个可以处理这样的参数的程序:

myProgram -i my_int=20 -s my_string=foo -f my_float=3.1415

进度
我当前的程序可以像这样执行:

myProgram -i 10 12 2 -s foobar anotherstring -f 3.1425 1.5
注意:没有值的名称
忽略多个值

我用boost program_options做了这个:

po::options_description desc("Allowed options");
desc.add_options()
    ("help", "produce help message")
    ("float,f", po::value< std::vector<float> >()->multitoken(), "add a float to the map")
    ("int,i", po::value< std::vector<int> >()->multitoken(),"add a int to the map")
    ("string,s", po::value< std::vector<std::string> >()->multitoken(),"add a string to the map")
    ;

我尝试了什么

我试图给po::value这种类型:
std::pair<std::string, std::vector<float> >
但这给了我一个complie错误

所以我的问题是:

  

是否可以使用boost库处理-s my_string=str之类的程序参数?

1 个答案:

答案 0 :(得分:1)

首先,这个语法让我感到更加参与,你可以考虑为它编写语法。

  

这使您可以更灵活地添加逻辑/约束,并且还可以更直接地解析为您想象的AST类型。有关此示例,请参阅此答案:

     

我发现了一种相对简单的方法,以防您将临时数据类型更改为std::vector<std::pair<std::string, T> >

由于使用lexical_cast<>进行转换,您可以读取任何输入可流式传输的值类型。让std::pair输入流式传输:

namespace std {
    template <typename V> static inline std::istream& operator>>(std::istream& is, std::pair<std::string, V>& into) {
        char ch;
        while (is >> ch && ch!='=') into.first += ch;
        return is >> into.second;
    }
}

现在,您可以进行说明:

desc.add_options()
    ("help", "produce help message")
    ("float,f",  po::value<Floats>()->multitoken(),  "add a float to the map")
    ("int,i",    po::value<Ints>()->multitoken(),    "add a int to the map")
    ("string,s", po::value<Strings>()->multitoken(), "add a string to the map")
    ;

让我们解析您的示例命令行

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm);
po::notify(vm);

并打印解析结果:

po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm);
po::notify(vm);

std::cout << "Floats:";    for (auto p : vm["float"].as<Floats>())   std::cout << " ['" << p.first << "' -> " << p.second << "]";
std::cout << "\nInts:";    for (auto p : vm["int"].as<Ints>())       std::cout << " ['" << p.first << "' -> " << p.second << "]";
std::cout << "\nStrings:"; for (auto p : vm["string"].as<Strings>()) std::cout << " ['" << p.first << "' -> " << p.second << "]";

<强> Live On Coliru

#include <boost/program_options.hpp>
#include <boost/program_options/cmdline.hpp>
#include <boost/any.hpp>
#include <vector>
#include <iostream>

namespace po = boost::program_options;

using Floats  = std::vector<std::pair<std::string, float>>;
using Ints    = std::vector<std::pair<std::string, int>>;
using Strings = std::vector<std::pair<std::string, std::string>>;

namespace std {
    template <typename V> static inline std::istream& operator>>(std::istream& is, std::pair<std::string, V>& into) {
        char ch;
        while (is >> ch && ch!='=') into.first += ch;
        return is >> into.second;
    }
}

int main(int argc, char** argv) {

    po::options_description desc("Allowed options");

    desc.add_options()
        ("help", "produce help message")
        ("float,f",  po::value<Floats>()->multitoken(),  "add a float to the map")
        ("int,i",    po::value<Ints>()->multitoken(),    "add a int to the map")
        ("string,s", po::value<Strings>()->multitoken(), "add a string to the map")
        ;


    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc, po::command_line_style::default_style), vm);
    po::notify(vm);

    std::cout << "Floats:";    for (auto p : vm["float"].as<Floats>())   std::cout << " ['" << p.first << "' -> " << p.second << "]";
    std::cout << "\nInts:";    for (auto p : vm["int"].as<Ints>())       std::cout << " ['" << p.first << "' -> " << p.second << "]";
    std::cout << "\nStrings:"; for (auto p : vm["string"].as<Strings>()) std::cout << " ['" << p.first << "' -> " << p.second << "]";
}

打印:

Floats: ['my_float' -> 3.1415]
Ints: ['my_int' -> 20]
Strings: ['my_string' -> foo]