c++ - 包含字符串成员作为合成属性的 Adapt 类

标签 c++ boost-spirit boost-fusion

我正在尝试将字符串解析为自定义类型的属性 symbol ,其中包含一个 std::string成员。我以为我可以使用 BOOST_FUSION_ADAPT_STRUCT在这里,但这不起作用。

如果我将规则声明为 rule<It, std::string(), space_type>有用。如果我将其定义为 rule<It, symbol(), space_type>它失败并显示错误“无类型名称 value_typesymbol ”。我认为 Spirit 正试图将值逐个字符附加到属性,这按预期失败了。但是有没有一种方法可以使这项工作无需添加捕获 std::string 的额外中间规则?属性?

这是完整的 MWE:

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>

struct symbol 
{ 
    std::string repr; 
};

BOOST_FUSION_ADAPT_STRUCT(symbol, (std::string, repr))

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct test_grammar : qi::grammar<Iterator, symbol(), qi::ascii::space_type> {
    test_grammar() : test_grammar::base_type{start} {
        start = qi::lexeme[+qi::char_("a-z")];
    }

    qi::rule<Iterator, symbol(), qi::ascii::space_type> start;
};

#include <iostream>

auto main() -> int {
    test_grammar<std::string::iterator> grammar{};
    auto input = std::string{"test"};
    auto output = symbol{};
    auto e = end(input);
    if (qi::phrase_parse(begin(input), e, grammar, qi::ascii::space, output))
        std::cout << output.repr;
}

最佳答案

正如您从链接的 dupe 中看到的那样,您可以使用适当放置的 qi::eps 来解决这个问题。

    start = qi::eps >> qi::lexeme[+qi::char_("a-z")];

查看 Live On Coliru

但是,有些情况下 qi::eps 不会保存。 (稍后将尝试查找链接)。因此,我开始赞成使用“老式方法”来实现属性兼容性:

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

struct symbol 
{ 
    std::string repr; 

    symbol(std::string repr = std::string()) : repr(std::move(repr)) {}
};

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct test_grammar : qi::grammar<Iterator, symbol(), qi::ascii::space_type> {
    test_grammar() : test_grammar::base_type(start) {
        using namespace qi;

        start = as_string[ lexeme[ +char_("a-z") ] ];
    }

    qi::rule<Iterator, symbol(), qi::ascii::space_type> start;
};

#include <iostream>

auto main() -> int {
    test_grammar<std::string::iterator> grammar{};
    auto input = std::string{"test"};
    auto output = symbol{};
    auto e = end(input);
    if (qi::phrase_parse(begin(input), e, grammar, qi::ascii::space, output))
        std::cout << output.repr;
}

这在编译器上也可能更轻一些。见<强>Live on Coliru 也是。

如果所有其他方法都失败了,您也可以吃蛋糕,因为属性转换/分配是库中的自定义点

关于c++ - 包含字符串成员作为合成属性的 Adapt 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21511731/

相关文章:

C++ char算术溢出

c++ - 在 boost spirit 中将属性传递给子规则

c++ - 实现一个对象目录:boost::any、boost::variant,或者?

c++ - 融合::vector + 融合::push_back = 融合::vector ?

c++ - 使用 boost::fusion::fold 将 boost::fusion::set 转换为 boost::fusion::map

c++ - 如何在 QML 中访问基于 QObjectList 的模型中的特定元素

c++ - boost python wrap c++​​类私有(private)成员

c++ - 我如何检查迭代器是否到达列表末尾?

boost-spirit - 使用 Spirit.Qi 消除语法糖

c++ - 我如何转发声明 boost::spirit 规则?