使用提升精神X3解析变体列表

时间:2017-07-06 12:55:44

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

我尝试将一个简单的float或int列表解析为variant的向量。我在Windows上使用boost 1.64(mingw 64bit)。

这是一个最小的例子:

#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>

#include <iostream>
#include <vector>

namespace x3 = boost::spirit::x3;

struct var : x3::variant<int, float> {
    using base_type::base_type;
    using base_type::operator=;
};

struct block {
    bool dummy; // needed to make newer boost version compile
    std::vector<var> vars;
};

BOOST_FUSION_ADAPT_STRUCT(block,
    (bool, dummy),
    (std::vector<var>, vars)
);

x3::rule<class var,   var>     const r_var   = "var";
x3::rule<class block, block>   const r_block = "block";

auto const r_var_def   = x3::float_ | x3::int_;
auto const r_block_def = x3::attr(true) >> *x3::lit(";") >> *(r_var >> -x3::lit(","));

BOOST_SPIRIT_DEFINE(r_var, r_block);

bool parse(std::string const &txt, block &ast)
{
    using boost::spirit::x3::phrase_parse;
    using boost::spirit::x3::space;

    auto iter = txt.begin();
    auto end = txt.end();

    const bool parsed = phrase_parse(iter, end, r_block, space, ast);
    return parsed && iter == end;
}

int main() {
    std::vector<std::string> list = {
        "1, 3, 5.5",
        ";1.0, 2.0, 3.0, 4.0"
    };

    for (const auto&i : list) {
        block ast;
        if (parse(i, ast)) {
            std::cout << "OK: " << i << std::endl;
        } else {
            std::cout << "FAIL: " << i << std::endl;
        }
    }
}

GCC 7.1出现以下错误:

..\parser\parser.cpp:41:68:   required from here
..\..\win64\include/boost/spirit/home/x3/nonterminal/detai/rule.hpp:313:24: error: use of deleted function 'var::var(const var&)'
             value_type made_attr = make_attribute::call(attr);
                        ^~~~~~~~~

任何想法,为什么海湾合作委员会不编译它?它与Clang合作。

直播Coliru(切换到clang ++以查看它是否有效)。

1 个答案:

答案 0 :(得分:4)

使用继承的特殊成员似乎存在问题。两个解决方法:

using var = x3::variant<int, float>;

可替换地:

struct var : x3::variant<int, float> {
    var            (          ) = default;
    var            (var const&) = default;
    var& operator= (var const&) = default;
    using base_type::base_type;
    using base_type::operator=;
};