一般情况:我不明白为什么我的 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:
编译器错误并不完全易于处理,要么文档有误,要么我误解了它.
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 a myderived
, and since base_
is fixed to type mybase
, we'd have to create a myderrived
from a mybase
and two int
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 types mybase
, int
and int
.
这篇关于检测 Spirit 语义动作中的参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!