gpt4 book ai didi

c++ - 在 add_options() 之后更改 boost::program_options 中的值语义。 IE。默认值

转载 作者:搜寻专家 更新时间:2023-10-31 00:40:43 27 4
gpt4 key购买 nike

我偶然发现了标题中定义的问题。我有一个创建 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com