检测 Spirit 语义动作中的参数类型
一般情况:我不明白为什么我的 Spirit 语法/语义动作没有编译.
General case: I can't figure out why my Spirit grammar/semantics actions aren't compiling.
有时,编译器会抱怨赋值或类型不兼容,我不知道出了什么问题.问题主要出现在两个方面:
Sometimes, the compiler will complain about assignment or type incompatibilities and I have no clue what's wrong. The problem occurs in two main areas:
- 预测规则/表达式的综合属性类型
- 因此,预测哪些类型的属性可以合法地定义为规则的公开属性(依赖于内置转换、融合适配器或 Spirit 自定义点)
- 编译器将能够编译函数调用
- 调用不会在过程中调用不必要的隐式转换
编译器错误并不完全易于处理,要么文档有误,要么我误解了它.
The compiler error is not exactly tractable, and either the documentation is wrong, or I misunderstood it.
无论如何,有没有办法确切地找出精神传递到我的语义动作中的内容?
Is there a way to find out exactly what Spirit passes into my semantic action, anyway?
struct mybase { int a,b; }; struct myderived : mybase { int c,d; }; BOOST_FUSION_ADAPT_STRUCT(mybase, (int,a)(int,b)); BOOST_FUSION_ADAPT_STRUCT(myderived, (int,a)(int,b)(int,c)(int,d)); auto base_expr = int_ >> int_; // avoids assigning to struct attribute rule<decltype(f), mybase() , space_type> base_ = int_ >> int_; rule<decltype(f), myderived(), space_type> derived_ = base_ >> int_ >> int_; myderived data; bool ok = phrase_parse(f,l,derived_,space,data);
此代码无法编译,存在大量难以理解的错误.
This code won't compile, with a huge amount of impenetrable errors.
(粗略改编自 精神一般列表)
推荐答案
为了清楚起见 - 这里的错误是
base_ >>内部_>>int_
被用作创建myderived
的规则的表达式,并且由于base_
固定为类型mybase
,我们d 必须从mybase
和两个int
创建一个myderrived
,但是没有什么可以告诉 Spirit 如何做到这一点.For clarity - the error here is that
base_ >> int_ >> int_
was used as the expression for a rule that creates amyderived
, and sincebase_
is fixed to typemybase
, we'd have to create amyderrived
from amybase
and twoint
s, but there's nothing to tell Spirit how to do that.您可以使用 boost 打印出 boost 通过解析
base_ >> 创建的值的类型.内部_>>int_
通过定义一个可以接受任何参数的函子,并告诉您它们是什么(以下代码改编自 SO chat 上的一些代码):You can get boost to print out the type of the value that boost creates from parsing
base_ >> int_ >> int_
by defining a functor that will take any parameters, and tell you what they are (the following code is adapted from some code sehe put on SO chat):struct what_is_the_attr { template <typename> struct result { typedef bool type; }; template <typename T> static void print_the_type() { std::cout << " "; std::cout << typeid(T).name(); if(std::is_const<typename std::remove_reference<T>::type>::value) std::cout << " const"; if(std::is_rvalue_reference<T>::value) std::cout << " &&"; else if(std::is_lvalue_reference<T>::value) std::cout << " &"; } template <typename Th, typename Th2, typename... Tt> static void print_the_type() { print_the_type<Th>(); std::cout << ", "; print_the_type<Th2, Tt...>(); } template <typename... Ts> void operator()(Ts&&...) const { std::cout << "what_is_the_attr( "; print_the_type<Ts...>(); std::cout << ")" << std::endl; } };
然后要使用它,请在初始化程序的语义操作中为您的错误规则使用上述角色:
Then to use it, use the above actor in a semantic action on initializer for your faulty rule:
std::string input = "1 2 3 4"; auto f(std::begin(input)), l(std::end(input)); rule<decltype(f), mybase() , space_type> base_ = int_ >> int_; rule<decltype(f), myderived(), space_type> derived_ = (base_ >> int_ >> int_)[what_is_the_attr()]; myderived data; bool ok = phrase_parse(f,l,derived_,space,data);
注意,您不能通过
%=
使用自动属性传播(除非您从规则的声明类型中删除了暴露的属性类型).Note, you cannot use automatic attribute propagation with
%=
(unless you remove the exposed attribute type from the rule's declared type).运行它应该会产生一个编码类型,可以用
c++filt -t
解码:生活在 Coliru 上Running this should then yield an encoded type, which can be decoded with
c++filt -t
: Live On Coliru$ g++ 9404189.cpp -std=c++0x $ ./a.out |c++filt -t what_is_the_attr( boost::fusion::vector3<mybase, int, int> &, boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil>, boost::fusion::vector0<void> > &, bool &)
第一行,
boost::fusion::vector3<mybase, int, int>
,至少告诉你 boost 正在尝试从 3 个mybase 类型的对象创建你的返回类型
、int
和int
.The first line,
boost::fusion::vector3<mybase, int, int>
, least tells you that boost is trying to create your return type from 3 objects of typesmybase
,int
andint
.
相关文章