C++ Boost程序的“组合()和隐式”值()选项不是;“组成”;
对于定义为composing()和implicit()的选项,我对boost program_选项(v1_49)有问题。我的意图是实现一个与perl类似的-D选项,以便您可以使用-D或-Dname并多次使用它。我的描述是:C++ Boost程序的“组合()和隐式”值()选项不是;“组成”;,c++,boost,boost-program-options,C++,Boost,Boost Program Options,对于定义为composing()和implicit()的选项,我对boost program_选项(v1_49)有问题。我的意图是实现一个与perl类似的-D选项,以便您可以使用-D或-Dname并多次使用它。我的描述是: ( "debug,D", bpo::value<vector<string> >() ->composing() ->implicit_value(vector<string>(1,"
( "debug,D",
bpo::value<vector<string> >()
->composing()
->implicit_value(vector<string>(1,"1")),
"Set debug level."
),
我想我明白了为什么会发生这种情况,隐式值{“1”}替换了现有的向量,而不是添加到它。我能做些什么来让它工作呢,还是它限制了boost::program_选项?嗯,我最终找到了一个似乎适合我的解决方案。如果可能的话,能有精通
boost::program_options
的人进行一些独立的验证会很好,但显然没有人知道或非常关心它
下面是一个增强_1_49_0的补丁,它将允许一个选项同时是composing()和一个隐式的_值()
diff-Naur old/boost/program\u options/detail/value\u semantic.hpp new/boost/program\u options/detail/value\u semantic.hpp
---旧的/增强的/程序选项/细节/值语义hpp 2010-07-12 03:14:14.000000000-0400
+++新建/增强/程序选项/详细信息/值语义hpp 2012-08-17 16:31:03.000000000-0400
@@ -154,6 +154,28 @@
}
}
+//用于将非向量隐式值复制到
+//标记向量。
+模板
+void get_隐式_标记(std::vector&vs,
+const boost::任何&a,
+T*,长){
+const T va=boost::任意掷骰(a);
+vs.push_back(boost::lexical_cast(va));
+ }
+
+//用于将向量隐式值复制到
+//标记向量。
+模板
+void get_隐式_标记(std::vector&vs,
+const boost::任何&a,
+std::vector*,int){
+const std::vector va=boost::any_cast(a);
+for(无符号i=0;i
这里有一个不需要修改boost源的解决方案。如果将解析和存储任务分开,则可以修改中间的boost::program_options::parsed_options
选项向量。向量的每个元素都包含std::string
键和值的std::vector
。解决方法依赖于这样一个事实:对于隐式值,该值向量是空的。如果我们扫描parsed_options
中的隐式值,并显式地为它们指定一个值,那么它们不会删除同一个键的先前值。以下是工作代码:
#include <iostream>
#include <string>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
namespace std {
// This overload is needed to use composed options.
static std::ostream& operator<<(
std::ostream& os,
const std::vector<std::string>& v) {
os << '{';
BOOST_FOREACH(const std::string& s, v) {
if (&s != &*v.begin())
os << ", ";
os << '"' << s << '"';
}
os << '}';
return os;
}
}
int main(int argc, char *argv[]) {
po::options_description desc("Allowed options");
desc.add_options()
("debug,D",
po::value<std::vector<std::string> >()
->composing()
->implicit_value(std::vector<std::string>(1,"1")),
"Set debug level.");
// Just parse the options without storing them in the map.
po::parsed_options parsed_options = po::command_line_parser(argc, argv)
.options(desc)
.run();
// Implicit option values are empty, replace with default value.
BOOST_FOREACH(po::option& o, parsed_options.options) {
if (o.string_key == "debug" && o.value.empty())
o.value.push_back("1"); // default value is "1"
}
// Now store and earlier values aren't clobbered.
po::variables_map vm;
po::store(parsed_options, vm);
po::notify(vm);
std::cout << "variables_map[\"debug\"] = "
<< (vm.count("debug") ?
vm["debug"].as<std::vector<std::string> >() :
std::vector<std::string>())
<< '\n';
return 0;
}
您可以尝试只使用
std::string
隐式值,而不是std::vector
值。不确定您的意思,隐式值的类型必须与值的类型匹配。如果没有,那么语句就不会编译。我在boost/program\u options/detail/value\u semantic.hpp:xparse()
:在value\u store=m\u implicit\u value代码>。有谁能帮忙建议一些附加到value\u store
而不是分配给它的方法吗?非常感谢,这是一种比修改boost代码更好的方法,特别是当我真的不知道我在那里做什么的时候。。。
diff -Naur old/boost/program_options/detail/value_semantic.hpp new/boost/program_options/detail/value_semantic.hpp
--- old/boost/program_options/detail/value_semantic.hpp 2010-07-12 03:14:14.000000000 -0400
+++ new/boost/program_options/detail/value_semantic.hpp 2012-08-17 16:31:03.000000000 -0400
@@ -154,6 +154,28 @@
}
}
+ // Helper function to copy a non-vector implicit value into the
+ // tokens vector.
+ template<class T, class charT>
+ void get_implicit_tokens(std::vector<std::basic_string<charT> >& vs,
+ const boost::any& a,
+ T*, long) {
+ const T va = boost::any_cast<const T>(a);
+ vs.push_back(boost::lexical_cast<std::basic_string<charT> >(va));
+ }
+
+ // Helper function to copy a vector implicit value into the
+ // tokens vector.
+ template<class T, class charT>
+ void get_implicit_tokens(std::vector<std::basic_string<charT> >& vs,
+ const boost::any& a,
+ std::vector<T>*, int) {
+ const std::vector<T> va = boost::any_cast<const std::vector<T> >(a);
+ for (unsigned i = 0; i < va.size(); i++) {
+ vs.push_back(boost::lexical_cast<std::basic_string<charT> >(va[i]));
+ }
+ }
+
template<class T, class charT>
void
typed_value<T, charT>::
@@ -164,7 +186,14 @@
// value, then assign the implicit value as the stored value;
// otherwise, validate the user-provided token(s).
if (new_tokens.empty() && !m_implicit_value.empty())
- value_store = m_implicit_value;
+ if (m_composing) {
+ // Attempt to append the implicit value.
+ std::vector<std::basic_string<charT> > vs;
+ get_implicit_tokens(vs, m_implicit_value, (T*)0, 0);
+ validate(value_store, vs, (T*)0, 0);
+ } else {
+ value_store = m_implicit_value;
+ }
else
validate(value_store, new_tokens, (T*)0, 0);
}
#include <iostream>
#include <string>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;
namespace std {
// This overload is needed to use composed options.
static std::ostream& operator<<(
std::ostream& os,
const std::vector<std::string>& v) {
os << '{';
BOOST_FOREACH(const std::string& s, v) {
if (&s != &*v.begin())
os << ", ";
os << '"' << s << '"';
}
os << '}';
return os;
}
}
int main(int argc, char *argv[]) {
po::options_description desc("Allowed options");
desc.add_options()
("debug,D",
po::value<std::vector<std::string> >()
->composing()
->implicit_value(std::vector<std::string>(1,"1")),
"Set debug level.");
// Just parse the options without storing them in the map.
po::parsed_options parsed_options = po::command_line_parser(argc, argv)
.options(desc)
.run();
// Implicit option values are empty, replace with default value.
BOOST_FOREACH(po::option& o, parsed_options.options) {
if (o.string_key == "debug" && o.value.empty())
o.value.push_back("1"); // default value is "1"
}
// Now store and earlier values aren't clobbered.
po::variables_map vm;
po::store(parsed_options, vm);
po::notify(vm);
std::cout << "variables_map[\"debug\"] = "
<< (vm.count("debug") ?
vm["debug"].as<std::vector<std::string> >() :
std::vector<std::string>())
<< '\n';
return 0;
}
$ ./a.out -D abc -D 255 -D xyz
variables_map["debug"] = {"abc", "255", "xyz"}
$ ./a.out -D -D 255 -D xyz
variables_map["debug"] = {"1", "255", "xyz"}
$ ./a.out -D abc -D -D xyz
variables_map["debug"] = {"abc", "1", "xyz"}
$ ./a.out -D abc -D 255 -D
variables_map["debug"] = {"abc", "255", "1"}