与解析器无关的函数的灵气语义动作和参数
我如何声明一个语义操作来调用一个不使用规则/解析器返回的属性的自由函数?
例如,假设我们有一个返回字符串的解析器,但我想调用一个不相关的函数,例如 Beep,它采用两个整数值作为频率和持续时间,并且不关心字符串?
实际上是否可以直接调用它,或者我总是必须编写一个代理函数来消耗字符串并调用(在本例中)其主体中的 Beep ?
编辑: 我很抱歉。 我应该提到,我首先使用了 boost::phoenix::bind 和 Hartmut 建议的语法,这给了我这个错误:
could not deduce template argument for 'RT (__cdecl *)(T0,T1)' from 'BOOL (__stdcall *)(DWORD,DWORD)'
是调用约定把这里的事情弄乱了吗?
编辑2: 看来这就是问题所在,Hartmuts 代码使用一个普通函数进行编译,该函数采用与 Beep 相同数量和类型的参数。
example:
bool foo(DWORD a, DWORD b)
{
}
px::bind(&foo,123,456); //compiles
px::bind(&Beep,123,456); // doesn't compile and generates the error message above.
谷歌搜索向我透露,(大多数)WINAPI 函数使用 __stdcall 约定,这不是默认约定 __cdecl,带有编译器选项 /Gd 的 C/C++ 函数使用该约定,如本例所示: foo
所以给出的答案是到目前为止都是正确的,凤凰解决方案对我来说并不是开箱即用的。 (这促使我首先提出这个问题。我很抱歉它的不尊严和令人困惑的性质,也许现在一切都清楚了。)
现在我唯一不清楚的是......我将如何让凤凰得到与 __stdcall 一起,但这可能应该是一个单独的问题。
How would I declare a semantic action that calls a free function that doesn't use the attribute the rule/parser returned?
Like, let's say we have a parser that returns a string, but I want to call an unrelated function like Beep, which takes two integer values for frequency and duration and does not care for strings?
Is it actually possible to call it directly, or do I always have to write a proxy function which consumes the string and calls, in this case, Beep in it's body?
Edit:
My apologies.
I should have mentioned that I used boost::phoenix::bind at first with the syntax Hartmut suggested, which gave me this error:
could not deduce template argument for 'RT (__cdecl *)(T0,T1)' from 'BOOL (__stdcall *)(DWORD,DWORD)'
Is it the calling convention that messes things up here?
Edit2:
Seems that's the problem, Hartmuts code compiles with a plain function that takes the same amount and types of arguments as Beep.
example:
bool foo(DWORD a, DWORD b)
{
}
px::bind(&foo,123,456); //compiles
px::bind(&Beep,123,456); // doesn't compile and generates the error message above.
A google search revealed to me that (most) WINAPI functions use the __stdcall convention, which is not the default convention, __cdecl, which C/C++ functions with the compiler option /Gd use, like in this case: foo
So the answers given so far were all correct, the phoenix solution just didn't work out of the box for me.
(Which motivated me to post this question in the first place. I'm sorry for it's undignified and confusing nature, maybe this clears it all up now.)
The only thing unclear to me now is...how I would make phoenix get along with __stdcall, but that should probably be a separate question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如约翰所说,您可以使用
boost::bind
。不过,您必须非常小心,不要混合和匹配来自不同库的占位符变量。使用boost::bind
时,您需要使用它的占位符变量,即::_1
(是的,boost::bind 的占位符位于全局命名空间中 - 恶心)。最好的解决方案(在兼容性方面也是最安全的)是利用
boost::phoenix::bind
。这与boost::bind
兼容,您可以做的任何事情都可以通过phoenix::bind
实现(甚至更多)。此外,Spirit “理解”Phoenix 使用特殊占位符变量构建并公开其所有内部结构,这些占位符变量是使用 Phoenix 本身实现的。在您的情况下,代码如下所示:
每当
some_parser
匹配时,它将调用Beep(123, 456)
。As John said you could use
boost::bind
. You have to be very careful not to mix and match placeholder variables from different libraries, though. When usingboost::bind
you need to use its placeholder variables, i.e.::_1
(yes, boost::bind's placeholders are in global namespace - yuck).The best solution (and the safest in terms of compatibility) is to utilize
boost::phoenix::bind
. This is compatible withboost::bind
and anything you can do there is possible withphoenix::bind
as well (and more). Moreover, Spirit 'understands' Phoenix constructs and exposes all of it's internals using special placeholder variables which are implemented using Phoenix themselves.In your case the code would look like:
which will call
Beep(123, 456)
wheneversome_parser
matches.我想你可以使用 Boost Bind。您可以这样做,而不是编写包装函数并将其地址提供给 Qi:
这将构建一个绑定,该绑定丢弃其自己的参数并调用
Beep(123, 456)
。如果您也想传递它的参数(不是在这里这样做,只是为了说明一些常见的事情),您可以这样做:然后它将调用
Beep(123, 456, the_string)
I imagine you can use Boost Bind. Instead of writing a wrapper function and giving its address to Qi, you could do this:
This will build a binding which discards its own arguments and calls
Beep(123, 456)
. If you wanted to pass its argument along as well (not that you do here, just to illustrate something common), you can do this:Then it will call
Beep(123, 456, the_string)