【发布时间】:2020-05-13 14:21:31
【问题描述】:
我正在尝试使用 boost::program_options 将 CLI 编写到使用大量 boost::optional 参数的现有代码库中,因此我想从命令行解析 boost::optional。如果不指定,结果是boost::none,如果指定了,我得到一个初始化值。
当我尝试使用自定义 Boost 验证器执行此操作时,我得到一个 bad_any_cast。以下是该问题的 MCVE。
我有课
class MyClass {
public:
int x;
MyClass(const int a) : x(a) {};
};
以及该类的自定义 Boost 验证器。这种风格的验证器直接取自 boost 文档。
void validate(boost::any& v, const std::vector<std::string>& values,
MyClass* target_type, int) {
v = boost::any(boost::optional<MyClass>(boost::in_place(1)));
}
最后,我的 main 函数创建了一个简单的解析器。
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/utility/in_place_factory.hpp>
int main(int argc, char** argv) {
po::options_description desc("");
desc.add_options()
("MyClass", po::value<boost::optional<MyClass>>()->default_value(boost::none, ""), "MyClass");
po::variables_map args;
po::store(po::parse_command_line(argc, argv, desc), args);
}
当我没有在命令行传递--MyClass选项时,代码运行成功。但是,如果我通过 --MyClass 选项,我会得到一个 bad_any_cast
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_any_cast> >'
what(): boost::bad_any_cast: failed conversion using boost::any_cast
我逐步完成了 GDB,这被扔进了 MyClass any_cast,但是如果我在 boost::program_options 之外编写类似的代码,它就会成功。
例如,以下代码将相同的 boost::optional 强制转换为 boost::any 然后将其强制转换回来,运行时不会出错。
#include <iostream>
#include <boost/program_options.hpp>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>
#include <boost/utility/in_place_factory.hpp>
namespace po = boost::program_options;
class MyClass {
public:
int x;
MyClass(const int a) : x(a) {};
};
int f(boost::any& v) {
v = boost::any(boost::optional<MyClass>(boost::in_place(1)));
}
int main(int argc, char** argv) {
boost::any v;
f(v);
boost::any_cast<boost::optional<MyClass>>(v);
}
我知道program_options 支持default_value,所以我可以在解析后使用 if 语句将基值包装在一个可选项中,但我认为使用上面的自定义验证器方法来实现这一点会更干净。
是否有人对如何解决此问题有任何想法或建议?
【问题讨论】:
-
您是否尝试将默认值从
boost::none更改为boost::optional<MyClass>()?boost::none与boost::optional<MyClass>()的类型不同,因此会导致 any 强制转换失败 -
boost::none实际上与boost::optional<T>兼容,并表示可选不包含值(即boost::optional<T> v.reset() == boost::none将评估为真)。此外,当any_cast应用于boost::none时,该代码有效,而当它应用于boost::none以外的任何内容时,代码就无效。不过感谢您的建议!