gpt4 book ai didi

c++ - 使用 Boost Spirit X3 和 Fusion 解析具有单个成员的结构变体

转载 作者:行者123 更新时间:2023-12-01 14:47:27 24 4
gpt4 key购买 nike

我正在尝试解析 std::Variant具有包含单个成员的 fusion 适应 Struct 类型。经过几个小时的尝试找出问题后,我能够使用以下代码重现该问题:

struct TestStruct {
float value;
};

BOOST_FUSION_ADAPT_STRUCT(TestStruct, value)

typedef std::variant<TestStruct, std:string> TestVariant;

auto TestStructRule = x3::rule<struct test_struct, TestStruct>{} = x3::float_ >> ",";

auto TestVariantRule = x3::rule<struct test_variant, TestVariant>{} = TestStruct | "default" >> x3::attr(std::String{"default"});
这会导致以下构建错误:
boost/boost/spirit/home/x3/support/traits/move_to.hpp:67:18: error: no viable overloaded '='

dest = std::move(fusion::front(src));

boost/boost/spirit/home/x3/support/traits/move_to.hpp:79:13: note: in instantiation of function template specialization 'boost::spirit::x3::traits::detail::move_to_plain<TestStruct, std::__1::variant<TestStruct, std::string> >' requested here

move_to_plain(std::forward<Source>(src), dest, is_single_element_sequence);

...

/Library/Developer/CommandLineTools/usr/include/c++/v1/variant:1214:12: note: candidate function not viable: no known conversion from 'typename remove_reference<float &>::type' (aka 'float') to 'const std::__1::variant<TestStruct, std::String>' for 1st argument

variant& operator=(const variant&) = default;
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/variant:1215:12: note: candidate function not viable: no known conversion from 'typename remove_reference<float &>::type' (aka 'float') to 'std::__1::variant<TestStruct, std::String>' for 1st argument

variant& operator=(variant&&) = default;
我觉得莫名其妙的是,如果我添加第二个成员到 TestStruct ,以下代码实际上可以正确编译和运行:
struct TestStruct {
float value1;
float value2; // <-- Added second member
};

BOOST_FUSION_ADAPT_STRUCT(TestStruct, value1, value2)

typedef std::variant<TestStruct, std:string> TestVariant;

auto TestStructRule = x3::rule<struct test_struct, TestStruct>{} = x3::float_ >> "," >> x3::float_ >> ",";

auto TestVariantRule = x3::rule<struct test_variant, TestVariant>{} = TestStruct | "default" >> x3::attr(std::String{"default"});
我还阅读了 SO,当尝试使用旧版本的 Spirit 解析这些时, fusion 适应的单字段结构存在已知问题。
使用 Spirit X3 解决(或绕过)此问题的最佳方法是什么?

最佳答案

我不想说,但这是一个众所周知的限制,它不断出现。我有点放弃尝试修复它。这是一种边缘情况,通常很容易解决或避免。
见例如

  • boost::spirit::x3 attribute compatibility rules, intuition or code?
  • How to move results parsed results into a struct using spirit x3
  • https://github.com/boostorg/spirit/pull/178

  • longer list exists for Qi .
    出于您的考虑,我可能会避免解析为 TestStruct而是解析为 float .否则,解析它并使用语义操作而不是自动属性传播进行传播。
    我尝试过并发现在这种特定情况下很难克服障碍(这似乎是“反向”问题,其中一个已经正确匹配的暴露 TestResult 的规则仍然会带来问题。显然,属性合成规则是又错了)。
    蛮力
    auto assign = [](auto& ctx) { _val(ctx) = _attr(ctx); };
    手动进行属性传播:
    auto test_struct
    = x3::rule<struct test_struct, TestStruct>{}
    = x3::float_ >> ",";

    auto test_variant
    = x3::rule<struct test_variant, TestVariant>{}
    = test_struct [assign] | "default" >> x3::attr("default"s)[assign];
    作品: Live On Coliru
    事实上,“官方”传播看起来更像是¹
    auto assign = [](auto& ctx) {
    x3::traits::move_to(_attr(ctx), _val(ctx));
    };
    它似乎不起作用: Live On Coliru

    ¹ 但不完全是,在此之前有很多元编程条件

    关于c++ - 使用 Boost Spirit X3 和 Fusion 解析具有单个成员的结构变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62628317/

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