在 boost program_options 中为 vector<string> 选项拆分值
Split value for vector<string> option in boost program_options
我正在开发一个通过配置文件读取一些选项的应用程序。该代码使用 boost program_options 库来读取选项。
应用程序代码有一个 class 执行以下与读取选项值相关的任务-
1)function1()
- 定义所有可能的有效选项。将它们添加到 option_description 对象。
2)function2()
- 解析配置文件并填充 variable_map 对象。
3)function3()
- returns option.This 函数的值如下所示 -
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>>()
returns 具有第一个元素的向量 - "value1,value2,value3"
我希望返回值是一个包含 3 个值的向量 - {"value1" , "value2" , "value3"}.
由于 function3() 是 class 中的模板化函数,我无法为 vector 编写专门的函数(例如使用 boost::split 拆分字符串)。
如果有办法,我会使用相同的矢量。
那么,有没有办法通过 program_options 固有地实现这一点?或在我的代码中实现此目的的任何其他建议?
您使用 Boost Program Options 的想法是使用 multi-token/composing 个选项。
跟着一起走
1)function1()
- defines all the possible options that are valid. Adds
them to an option_description
object.
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()
- parses the
config file and populates the variable_map
object.
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()
-
returns the value of an option.This function looks like this -
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"
I want the returned value to be a vector containing 3 values - {"value1" , "value2" , "value3"}.
已经完成,看到了Live On Coliru
Since function3() is a templatized function in the class, I cannot write a specialized function for vector(that would split the string say, using 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"
再看一遍Live On Coliru
奖金
如果你想要部分专业化,要么将 function3
的实现委托给模板 class,要么使用标签分派。这将使 possible/easy 也解析为 set<int>
或 list<bool>
。
我正在开发一个通过配置文件读取一些选项的应用程序。该代码使用 boost program_options 库来读取选项。
应用程序代码有一个 class 执行以下与读取选项值相关的任务-
1)function1()
- 定义所有可能的有效选项。将它们添加到 option_description 对象。
2)function2()
- 解析配置文件并填充 variable_map 对象。
3)function3()
- returns option.This 函数的值如下所示 -
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>>()
returns 具有第一个元素的向量 - "value1,value2,value3"
我希望返回值是一个包含 3 个值的向量 - {"value1" , "value2" , "value3"}.
由于 function3() 是 class 中的模板化函数,我无法为 vector 编写专门的函数(例如使用 boost::split 拆分字符串)。
如果有办法,我会使用相同的矢量。
那么,有没有办法通过 program_options 固有地实现这一点?或在我的代码中实现此目的的任何其他建议?
您使用 Boost Program Options 的想法是使用 multi-token/composing 个选项。
跟着一起走
1)
function1()
- defines all the possible options that are valid. Adds them to anoption_description
object.
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()
- parses the config file and populates thevariable_map
object.
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()
-
returns the value of an option.This function looks like this -
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"
I want the returned value to be a vector containing 3 values - {"value1" , "value2" , "value3"}.
已经完成,看到了Live On Coliru
Since function3() is a templatized function in the class, I cannot write a specialized function for vector(that would split the string say, using 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"
再看一遍Live On Coliru
奖金
如果你想要部分专业化,要么将 function3
的实现委托给模板 class,要么使用标签分派。这将使 possible/easy 也解析为 set<int>
或 list<bool>
。