gpt4 book ai didi

c++ - Boost Karma:在未设置 boost::optional 时生成默认文本

转载 作者:行者123 更新时间:2023-11-30 03:25:57 26 4
gpt4 key购买 nike

考虑以下程序:

using FooVariant = boost::variant<std::string, int>;
using FooOptional = boost::optional<FooVariant>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator
: boost::spirit::karma::grammar<OutputIt, FooOptional()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

foovar_ = bsk::auto_;
start_ = -foovar_;
}

boost::spirit::karma::rule<OutputIt, FooVariant()> foovar_;
boost::spirit::karma::rule<OutputIt, FooOptional()> start_;
};

int main()
{
FooVariant fv = "foo";
FooOptional fo = fv;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

正如预期的那样,这将打印 foo .同样,如果我初始化 fo只需:

FooOptional fo;

然后程序将不打印任何内容,同样符合预期。但是我不想打印任何东西,而是打印 -反而。所以,我更改了 start_ 的规则到:

start_ = (foovar_ | '-');

但这会导致编译错误:

alternative_function.hpp:127:34: error: no member named 'is_compatible' in 'boost::spirit::traits::compute_compatible_component, int>, boost::optional, int> >, boost::spirit::karma::domain>' if (!component_type::is_compatible(spirit::traits::which(attr_))) ~~~~~~~~~~~~~~~~^

我还注意到,如果我删除 FooVariant而是制作 FooOptional = boost::optional<int>并更新我的生成器,如果我向它传递一个未设置的可选值,我可能会产生崩溃。例如:

int main()
{
FooOptional fo;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

这让我相信我错误地使用了可选代。执行此操作的正确方法是什么?

更新

进一步调查后,我发现了一些有趣的事情。我修改后的代码是:

using FooVariant = boost::variant<std::string, int>;
using FooOptional = boost::optional<int>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator
: boost::spirit::karma::grammar<OutputIt, FooOptional()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

foovar_ = bsk::int_;
start_ = (bsk::int_ | '-');
}

boost::spirit::karma::rule<OutputIt, int()> foovar_;
boost::spirit::karma::rule<OutputIt, FooOptional()> start_;
};

int main()
{
FooOptional fo;
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}

它的工作原理是它将打印 -或整数值,如果分配了一个(不在粘贴的代码中)。然而,当我改变我的 start_规则:

start_ = (foovar_ | '-');

我在空值上崩溃。

最佳答案

我同意这似乎不像您希望的那样有效。也许实用的简化是将“Nil”表示为变体元素类型:

struct Nil final {};

using FooVariant = boost::variant<Nil, std::string, int>;

现在默认构造的 FooVariant 将包含 Nil。规则简单地变成了:

    start_  = string_ | bsk::int_ | "(unset)";

演示

Live On Wandbox

#include <boost/spirit/include/karma.hpp>

struct Nil final {};

using FooVariant = boost::variant<Nil, std::string, int>;

template<typename OutputIt = boost::spirit::ostream_iterator>
struct FooGenerator : boost::spirit::karma::grammar<OutputIt, FooVariant()>
{
FooGenerator()
: FooGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;

string_ = '"' << *('\\' << bsk::char_("\\\"") | bsk::print | "\\x" << bsk::right_align(2, '0')[bsk::hex]) << '"';
start_ = string_ | bsk::int_ | "(unset)";
}

boost::spirit::karma::rule<OutputIt, std::string()> string_;
boost::spirit::karma::rule<OutputIt, FooVariant()> start_;
};

int main() {
for (auto fo : { FooVariant{}, {FooVariant{42}}, {FooVariant{"Hello\r\nWorld!"}} }) {
std::cout << boost::spirit::karma::format(FooGenerator<>(), fo) << std::endl;
}
}

打印

(unset)
42
"Hello\x0d\x0aWorld!"

关于c++ - Boost Karma:在未设置 boost::optional 时生成默认文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48671117/

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