【问题标题】:boost spirit x3 (A | A) attribute type is variant<A, ?> instead of Aboost spirit x3 (A | AN) 属性类型是 variant<A, ?> 而不是 A
【发布时间】:2017-02-10 07:31:43
【问题描述】:

我正在尝试创建一个简单的解析器,它使用boost::spirit::x3 获取两个可能的字符之一。问题是x3::char_('#') | x3::char_('.') 似乎有一个boost::variant&lt;char, ?&gt; 类型的属性。这意味着我必须在_attr 上使用boost::get&lt;char&gt;,而它应该可以直接转换为char

http://ciere.com/cppnow15/x3_docs/spirit/quick_reference/compound_attribute_rules.html,上面写着A | A -&gt; A

如果使用注释掉的mapChars 版本,则它可以转换为char,但不能转换为|

我使用的是 boost 版本 1.63.0 和 Linux。代码无法在带有-std=c++14 的 g++ 和 clang++ 上编译。

我做错了什么?

#include <iostream>
#include <string>

#include <boost/spirit/home/x3.hpp>

int main() {
    std::string s("#");
    namespace x3 = boost::spirit::x3;
    auto f = [](auto & ctx) {
        auto & attr = x3::_attr(ctx);
        //char c = attr; // doesn't work
        char c = boost::get<char>(attr); // does work
    };
    auto mapChar = x3::char_('#') | x3::char_('.'); // _attr not convertible to char, is a variant
    //auto mapChar = x3::char_('#'); // _attr convertible to char, isn't a variant
    auto p = mapChar[f];
    auto b = s.begin();
    bool success = x3::parse(b, s.end(), p);
    std::cout << "Success: " << success << ' ' << (b == s.end()) << '\n';
}

【问题讨论】:

  • 我认为x3::char_("#.") 应该做你想做的事。当然这并不能解决A|A-&gt;variant&lt;A&gt;的问题。
  • 对于这个示例,这是非常等价的

标签: c++ boost boost-spirit boost-spirit-x3


【解决方案1】:

你是对的,它应该是兼容的,而且确实已经是:

auto const& attr = x3::_attr(ctx);
char c;
x3::traits::move_to(attr, c);

Spirit 的属性兼容规则(加上自定义点)是承载这种语义的载体。

我同意你的观点,如果属性类型可以直接简化为char,这可能是一个很好的可用性改进,但我认为这会在未来产生更深远的影响。

【讨论】:

  • 我试过了,这基本上给出了相同的错误 (assigning to char from incompatible type ...&lt;variant&lt;...&gt;&gt;...)。在这种情况下,x3::traits::move_to 似乎只是在做dest = std::move(src);,这并没有改变任何东西。
  • @aeubanks 嗯。你说得很对。我一定做错了什么。同时,您可以使用规则强制(demo),它变得更加方便with a helper functioncoliru.stacked-crooked.com/a/1f5788a7eeaf872b
  • 如果您认为应该讨论这个问题以进行改进,您可以通过 [spirit-general] 邮件列表联系开发人员
【解决方案2】:

如果您的语义操作按值获取属性,它应该可以工作:

char result = 0;

auto f = [&result](char c){ result = c; };

auto mapChar = x3::char_('#') | x3::char_('.');
auto p = mapChar[f];
auto b = s.begin();
bool success = x3::parse(b, s.end(), p);

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 2021-06-06
    • 1970-01-01
    • 2012-01-19
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 2012-06-06
    相关资源
    最近更新 更多