与解析器无关的函数的灵气语义动作和参数

发布于 2024-11-03 16:19:57 字数 938 浏览 1 评论 0原文

我如何声明一个语义操作来调用一个不使用规则/解析器返回的属性的自由函数?

例如,假设我们有一个返回字符串的解析器,但我想调用一个不相关的函数,例如 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゞ记忆︶ㄣ 2024-11-10 16:19:57

正如约翰所说,您可以使用 boost::bind。不过,您必须非常小心,不要混合和匹配来自不同库的占位符变量。使用 boost::bind 时,您需要使用它的占位符变量,即 ::_1 (是的,boost::bind 的占位符位于全局命名空间中 - 恶心)。

最好的解决方案(在兼容性方面也是最安全的)是利用 boost::phoenix::bind。这与 boost::bind 兼容,您可以做的任何事情都可以通过 phoenix::bind 实现(甚至更多)。此外,Spirit “理解”Phoenix 使用特殊占位符变量构建并公开其所有内部结构,这些占位符变量是使用 Phoenix 本身实现的。

在您的情况下,代码如下所示:

namespace phx = boost::phoenix;
some_parser[phx::bind(&Beep, 123, 456)];

每当 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 using boost::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 with boost::bind and anything you can do there is possible with phoenix::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:

namespace phx = boost::phoenix;
some_parser[phx::bind(&Beep, 123, 456)];

which will call Beep(123, 456) whenever some_parser matches.

一张白纸 2024-11-10 16:19:57

我想你可以使用 Boost Bind。您可以这样做,而不是编写包装函数并将其地址提供给 Qi:

boost::bind( Beep, 123, 456 );

这将构建一个绑定,该绑定丢弃其自己的参数并调用 Beep(123, 456)。如果您也想传递它的参数(不是在这里这样做,只是为了说明一些常见的事情),您可以这样做:

boost::bind( Beep, 123, 456, _1 );

然后它将调用 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:

boost::bind( Beep, 123, 456 );

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:

boost::bind( Beep, 123, 456, _1 );

Then it will call Beep(123, 456, the_string)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文