- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我偶然发现了标题中定义的问题。我有一个创建 options_description
实例然后在其上使用 add_options()
的应用程序。与示例中的非常相似:
options_description desc;
desc.add_options()
("help", "produce help")
("optimization", value<int>()->default_value(10), "optimization level")
;
我的问题是,如何在调用之后修改optimization
的默认值。这可能吗?文档对我来说似乎很模糊。据我了解,这个问题可以推广到任何值语义,因为 value_semantic
是括号中的第二个参数。
动机
我觉得这可能是不可能的。因此,我想介绍一下我对此类功能的动机。也许我的意图设计有缺陷,所以你可以提出其他建议。
我有几个程序执行非常相似的任务并共享相当多的参数和开关。我想我可以将公共(public)参数重构为一个单独的基类。我虽然可以重构以类似方式解析的命令行。 boost::program_options
确实很符合我的想法。我将 options_description
实例构建为基类中的私有(private)属性,并在其中添加常用选项。然后在初始化后的派生类中,我再次在此对象上执行 add_options()
添加更多特定选项。这看起来非常简洁,我很快就让它工作了。
然后我注意到所有的派生类都有一个共同的选项,但是如果它有一个不同的默认值就太好了。 IE。输出文件的名称。对于 app1 为 app1.out,app2 - app2.out 等。
当然,我可以将输出文件名选项移动到派生类中的add_options
,但这看起来很愚蠢和多余,因为即使在语义上,除了默认值之外,其他一切都是一样的。另一种解决方法是放弃基类中的默认值,并在派生类的解析后步骤中检查是否设置了该选项并手动应用(默认)值。然而,这似乎也是多余的,因为预期的功能似乎是在库本身中实现的。
我将尝试提供一个代码示例,以便您稍后或根据要求更好地感受它。不过,我认为我的方法很明确。
编辑 - 代码示例它是在 Rob 的回答之后写的,所以我尽量遵守命名约定。
Base - 执行解析并允许将优化级别设置为整数:
#include <boost/program_options.hpp>
namespace po = boost::program_options;
class BaseClass {
public:
BaseClass::BaseClass();
virtual int parse(const int argc, char** argv);
private:
po::options_description m_desc;
po::variables_map vm;
int optimization_level;
};
BaseClass::BaseClass():
m_desc()
{
m_desc.add_options()
("help", "produce help")
("optimization", value<int>()->default_value(10), "optimization level")
;
}
int BaseClass::parse(const int argc, char** argv)
{
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) { std::cout << desc << "\n"; return 1; }
optimization_level = vm["optimization"].as<int>();
return 0;
}
高度优化的版本,允许有选择地执行花哨的东西:
class HighlyOptimizedClass : public BaseClass {
public:
HighlyOptimizedClass();
virtual int parse(const int argc, char** argv);
private:
bool fancy_optimizations;
};
HighlyOptimizedClass(): BaseClass() {
m_desc.add_options()
("fancy,f", po::value<bool>()->zero_tokens(), "perform fancy optimizations")
;
}
HighlyOptimizedClass::parse(const int argc, char** argv)
{
int ret = BaseClass::parse(argc, argv); //execute base function
if( ret ) return ret; //return if it didnt succed
if ( vm.count("fancy") ) fancy_optimizations = 1; // non-base stuff
return 0;
}
允许打开详细调试的非优化版本:
class NonOptimizedClass : public BaseClass {
public:
NonOptimizedClass();
virtual int parse(const int argc, char** argv);
private:
bool verbose_debug;
};
NonOptimizedClass(): BaseClass() {
m_desc.add_options()
("verbose,v", po::value<bool>()->zero_tokens(), "genrates TONS of output")
;
}
NonOptimizedClass::parse(const int argc, char** argv)
{
int ret = BaseClass::parse(argc, argv); // execute base function
if( ret ) return ret; // return if it didnt succed
if ( vm.count("verbose") ) verbose_debug = 1; // non-base stuff
return 0;
}
我试着垂直压缩它,但它还是变长了=/。对不起,如果我过火了。反过来,示例清晰且自包含。
BaseClass
设置几乎所有内容并解析常见内容。派生类在构造函数和重载解析中添加自己的选项。他们执行基本解析器并检查错误。这也使 --help
工作。
现在要做的是修改每个派生的优化默认值。最好将 NonOptimizedClass
设置得非常低,将 OptimizedClass
设置得非常高。
最佳答案
您可以调用 options_description::find("optimization", ...)
获得对相关 option_description
的引用, 及其 semantic
方法将为您提供指向 value_semantic
的指针您最初在调用 add_options
时提供的.但是,它是一个 const 指针,因此您似乎不能修改它指向的内容。
然而,value_semantic
在您创建它时它不是 const,这意味着使用它应该是安全的 const_cast
删除 option_description
的 const 限定条件适用。您还必须对 value_semantic
进行类型转换对象回到右边typed_value
最初调用 value<T>
时获得的类型.
option_description const& optimization = desc.find("optimization", false);
shared_ptr<const value_semantic> cvalue = optimization.semantic();
shared_ptr<value_semantic> value = const_pointer_cast<value_semantic>(cvalue);
shared_ptr<typed_value<int>> tvalue = dynamic_pointer_cast<typed_value<int>>(value);
assert(tvalue);
tvalue->default_value(20);
另一种设计可以避免在定义选项后修改选项(这显然不是 program_options
设计的目的),是让程序特定的派生类将所需的默认值传递给基类。然后基类可以在定义优化选项时使用该值。
BaseClass::BaseClass(int default_optimization):
m_desc()
{
m_desc.add_options()
("help",
"produce help")
("optimization",
value<int>()->default_value(default_optimization),
"optimization level")
;
}
HighlyOptimizedClass::HighlyOptimizedClass():
BaseClass(99)
{ }
NonOptimizedClass::NonOptimizedClass():
BaseClass(0)
{ }
关于c++ - 在 add_options() 之后更改 boost::program_options 中的值语义。 IE。默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14245801/
我正在尝试解析从命令行输入的列表。 我的类是从向量派生的 编译器提示重载验证不明确。我知道为什么,但不知道如何解决这个问题。 请帮忙。 下面是一个生成错误的最小示例。如果将 ch_list 的类型更改
使用 boost::program_options,当它在命名空间内声明时,我无法获得自己的选项类型进行编译。但是在命名空间之外它编译并工作正常: #include using namespace
我目前正在尝试在我的模拟中实现 boost::program_options 库。在读取(许多)参数时,我想做这样的事情 namespace po = boost::program_options;
我目前正在尝试重做一些传递给我的代码。代码的原始点是读取配置文件,并在boost::program_options::variable_map中设置文件中的不同选项,然后读取该代码的其他所有部分,这些
我正在尝试使用 Boost::program_options 读取配置文件。配置文件如下所示: hier.arch.y.option_name = 0x5 another.hier.archy.set
#include #include #include #include void basic_approach(int argc, char const *argv[]) { try
我无法找出使用 boost::program_options 的链接错误。这是一个示例 C++ 代码: # sample_code.cpp #include int main() { boo
我正在尝试在配置文件的值中使用井号 ('#')。 我的用例是一个音乐程序,其中的值给出了吉他乐谱的调音。因此,在值中支持“#”是强制性的,并且不支持任何解决方法,这与可以使用“b”模拟的平面不同。 我
我正在尝试了解 program_options 自定义验证,以便将 python 代码转换为 c++ 代码。 无论如何 我在示例中读到我必须重载验证函数 我试图在 boost program_opti
我目前正在阅读 Boost.Program_options 教程。 这是他们介绍的一些代码: // Declare the supported options. po::options_descrip
海湾合作委员会 4.7.2/ boost 1.58.0 我正在尝试看起来像这样的代码,几乎完全取自文档中的示例: namespace po = boost::program_options; po::
我使用 ubuntu 10.04 和 libboost1.40。 ls -l /usr/lib | grep boost_pro -rw-r--r-- 1 root root 64080
boost::program_options 似乎支持某种级别的 custom validation但对我来说,验证是根据类型而不是每个参数编写的,这似乎很奇怪,我想知道我是否在这里遗漏了什么。 例如
构建我的项目时,Boost_LIBRARIES 不包含 program_options,即使它是必需的并且已找到。如果我手动添加它,它工作正常。我的 CMake 包含以下内容: find_packag
我对 boost::program_options 有疑问 我有课 namespace po = boost::program_options; class imageProcess{ private
program_options 是少数几个不只是头文件(因此需要单独编译)的 Boost 库之一。 我需要在未安装 Boost 的集群中运行我在 PC 上编译的程序。我没有安装 Boost 的管理权限
在 debian stretch 和 gcc 6.4.0 上,boost 1.66.0 boost::program_options 总是用空值解析命令行。代码如下: #include #inclu
我正在尝试从源代码构建第 3 方 C++ 库,它依赖于 Boost。在构建的最后一步,我得到了这样的错误: [ 90%] Linking CXX executable Shannon_RNASeq_C
我在使用 boost:program_options 时遇到问题 这个简单的程序,从 boosts 的文档中复制粘贴: #include int main( int argc, char** arg
一开始不解析参数,而是在程序已经运行了一段时间的某个时间解析从管道读取的输入字符串。 boost::program_options 可以这样做吗? 谢谢。编辑: 我必须在 python 中使用不同的参
我是一名优秀的程序员,十分优秀!