问题描述
我正在尝试使用Boost 1.65.1中的Spirit X3来创建解析器.我已将问题简化为以下具有更简单结构的较小示例:
I'm trying to use Spirit X3 from Boost 1.65.1 to make a parser. I have reduced my problem to the following smaller example with simpler structures:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <vector>
struct MyPair {
MyPair(int x, int y) : mx(x), my(y) {};
//MyPair() {} // No default constructor - neither needed nor wanted.
int mx;
int my;
};
/*
BOOST_FUSION_ADAPT_STRUCT(
MyPair,
(int, mx)
(int, my)
)
*/
int main()
{
using boost::spirit::x3::int_;
using boost::spirit::x3::parse;
std::vector<MyPair> pairs;
char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first);
auto pair = [&](auto& ctx) { return MyPair(1, 2); };
bool parsed_some = parse(first, last, ((int_ >> ':' >> int_)[pair]) % ',', pairs);
if (parsed_some) {
std::cout << "Parsed the following pairs" << std::endl;
for (auto& p : pairs) {
std::cout << p.mx << ":" << p.my << std::endl;
}
}
return 0;
}
我不想向我的类型(此处为MyPair)添加默认构造函数.如果没有默认的构造函数,则会出现以下错误:
I do not want to add a default constructor to my type (here MyPair). Without a default constructor I get the following error:
'MyPair::MyPair': no appropriate default constructor available ...\boost\utility\value_init.hpp
但是我不想将结构更改为具有默认构造函数.假设我确实添加了一个,我得到的最后一个错误是:
But I do not want to change my structures to have a default constructor. Suppose, I do add one, the last error I get is:
binary '=': no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) TestParsing ...\x3\support\traits\move_to.hpp
但是由于我是通过语义动作手动构造属性的,所以我看不到为什么需要进行融合定义. (请注意,当前它使用硬编码的值,直到解决此问题,然后获得正确的值为止).
But since I manually construct the attribute in a semantic action I do not see why I need to make a fusion definition. (Note, that currently it uses hardcoded values, until I get this problem fixed, and then get the proper value out).
如何使用Spirit X3在没有默认构造函数的情况下构造用户定义类型的属性?
How do I construct attributes of user-defined type without default constructors using Spirit X3?
推荐答案
想到的唯一方法就是完全避免将规则/解析器绑定到MyPair
属性.
The only way that comes to mind is too avoid having a rule/parser that binds to a MyPair
attribute at all.
幸运的是,X3足够灵活,可以重复绑定到容器属性:
Fortunately X3 is flexible enough to bind to a container attribute repeatedly:
auto pair = x3::rule<struct pair_, std::vector<MyPair> > {}
= (int_ >> ':' >> int_)
[([&](auto& ctx) {
auto& attr = x3::_attr(ctx);
using boost::fusion::at_c;
return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr));
})]
;
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include <vector>
struct MyPair {
MyPair(int x, int y) : mx(x), my(y) {};
int mx;
int my;
};
int main()
{
namespace x3 = boost::spirit::x3;
using x3::int_;
std::vector<MyPair> pairs;
char const *first = "11:22,33:44,55:66", *last = first + std::strlen(first);
auto pair = x3::rule<struct pair_, std::vector<MyPair> > {}
= (int_ >> ':' >> int_)
[([&](auto& ctx) {
auto& attr = x3::_attr(ctx);
using boost::fusion::at_c;
return x3::_val(ctx).emplace_back(at_c<0>(attr), at_c<1>(attr));
})]
;
bool parsed_some = parse(first, last, pair % ',', pairs);
if (parsed_some) {
std::cout << "Parsed the following pairs" << std::endl;
for (auto& p : pairs) {
std::cout << p.mx << ":" << p.my << std::endl;
}
}
}
打印
Parsed the following pairs
11:22
33:44
55:66
这篇关于没有默认构造函数的Boost-Spirit(X3)解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!