分割向量<string>选项的值,在boost program_options中。

问题描述 投票:2回答:1

我正在做一个通过配置文件读取一些选项的应用程序。代码使用 boost program_options库来读取选项。

应用程序代码中有一个类,它做了以下与读取选项值相关的任务------。

1)function1() - 定义了所有可能有效的选项。将它们添加到一个 option_description 对象中。2)function2() - 解析配置文件并填充变量_map对象。3)function3() - 返回一个选项的值。这个函数看起来像这样--。

template<typename T>
T function3(string optName){
    try{return vm[optName].as<T>();}
    catch(exception& e){ //some error handling message}
}

现在,对于一个选项,如

vector_of_string_option=value1,value2,value3

为此,我将这个选项添加到选项描述对象中,作为

("vector_of_string_option", po::value<vector<string>>(), "vector string");

为此 vm["vector_of_string_option"].as<vector<string>>() 返回一个有第一个元素的向量- "value1,value2,value3"

我希望返回的值是一个包含3个值的向量--{"value1" , "value2" , "value3"}。

由于 function3() 是类中的模板化函数,我不能为 vector 写一个专门的函数(例如,使用 boost::split 来分割字符串)。

如果有办法的话,我也会用在向量上。

那么,有没有一种方法可以通过program_options来实现这个功能呢? 或者有什么其他建议可以在我的代码中实现这个功能?

c++ boost boost-program-options
1个回答
1
投票

你使用Boost程序选项的想法是使用多令牌组成的选项。

让我们跟着来看看

1)function1() - 定义了所有可能的有效选项。将它们添加到一个 option_description 对象。

auto function1() {
    po::options_description desc;
    for (auto opt : s_opts)
        desc.add_options()(opt, po::value<std::string>());
    desc.add_options()
        ("vector_of_string_option", po::value<VoS>()->multitoken()->composing(), "vector string")
        ;
    return desc;
}

到目前为止还不错

2)function2() - 解析配置文件并填充 variable_map 对象。

auto function2(std::istream&& is) {
    auto d = function1();
    po::parsed_options parsed = po::parse_config_file(is, d, false);
    po::variables_map vm;
    po::store(parsed, vm);
    po::notify(vm);

    return vm;
}

还是没有问题。

3)function3() -

返回一个选项的值.这个函数看起来像这样--------。

template <typename T>
T function3(std::string optName, po::variables_map const& vm) {
    try {
        return vm[optName].as<T>();
    } catch (std::exception const& e) {
        std::cerr << "Whoops: " << e.what() << "\n";
        exit(1);
    }
}

好的。

int main() {
    auto vm = function2(std::istringstream(R"(
bar=BARRRR
# bar=QUXXXX # "cannot be specified more than once"
vector_of_string_option=value1
vector_of_string_option=value2
vector_of_string_option=value3
)"));
    std::cout << function3<std::string>("bar", vm) << "\n";
    for (auto& v : function3<VoS>("vector_of_string_option", vm)) {
        std::cout << " - " << std::quoted(v) << "\n";
    }
}

打印。

BARRRR
 - "value1"
 - "value2"
 - "value3"

我希望返回的值是一个包含3个值的向量 {"value1", "value2", "value3"}.

已有 妥当,看到它 活在科利鲁

由于function3()是类中的模板化函数,我不能为vector写一个专门的函数(比如使用boost::split来分割字符串)。

你当然可以! 你不能部分特化,但你可以特化。

template <>
VoS function3<VoS>(std::string optName, po::variables_map const& vm) {
    try {
        VoS result;
        auto const& raw = vm[optName].as<VoS>();

        using namespace boost::algorithm;
        for(auto& rv : raw) {
            VoS tmp;
            split(tmp, rv, is_any_of(",; "), token_compress_on);
            result.insert(result.end(), tmp.begin(), tmp.end());
        }
        return result;
    } catch (std::exception const& e) {
        std::cerr << "Whoops: " << e.what() << "\n";
        exit(1);
    }
}

这使得你可以使用多个值,但也可以拆分每个值。

int main() {
    auto vm = function2(std::istringstream(R"(
bar=BARRRR
# bar=QUXXXX # "cannot be specified more than once"
vector_of_string_option=value1, value2, value3
vector_of_string_option=value4, value5, value6
)"));
    std::cout << function3<std::string>("bar", vm) << "\n";
    for (auto& v : function3<VoS>("vector_of_string_option", vm)) {
        std::cout << " - " << std::quoted(v) << "\n";
    }
}

打印

BARRRR
 - "value1"
 - "value2"
 - "value3"
 - "value4"
 - "value5"
 - "value6"

再来看看 活在科利鲁

奖励措施

如果你想要部分特殊化,要么委托实现 function3 到一个模板类,或者使用标签派遣。这样就可以很容易地将其解析为 set<int>list<bool> 以及。

稿。http:/coliru.stacked-crooked.coma7971dd671010d38e。

© www.soinside.com 2019 - 2024. All rights reserved.