2

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

就像,假设我们有一个返回字符串的解析器,但我想调用一个不相关的函数,比如 Beep,它接受频率和持续时间的两个整数值并且不关心字符串?

实际上是否可以直接调用它,或者我是否总是必须编写一个使用字符串并调用的代理函数,在这种情况下,Beep in it's body?

编辑:我很抱歉。我应该提到我最初使用了 boost::phoenix::bind 和 Hartmut 建议的语法,这给了我这个错误:

could not deduce template argument for 'RT (__cdecl *)(T0,T1)' from 'BOOL (__stdcall *)(DWORD,DWORD)'

是调用约定把事情搞砸了吗?

Edit2:似乎这就是问题所在,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

所以到目前为止给出的答案都是正确的,凤凰解决方案对我来说并不是开箱即用的。(这促使我首先发布这个问题。我很抱歉它的不尊严和令人困惑的性质,也许现在这一切都清楚了。)

我现在唯一不清楚的是......我将如何让 phoenix 与 __stdcall 相处,但这可能应该是一个单独的问题。

4

2 回答 2

2

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

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.

于 2011-04-27T00:39:47.947 回答
1

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

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

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

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

然后它会调用Beep(123, 456, the_string)

于 2011-04-26T12:26:40.870 回答