从最简单的开始:
为什么它不像在绑定和函数中那样工作?
因为宏是为函数设计的,而不是为成员函数设计的。指向成员函数的指针与函数指针非常不同,所以这就是路的尽头。
在您的示例中,A::foo 实际上不需要是 实例方法(非静态成员函数),因此只需添加 static(和隐式参数)即可完成:
struct A {
static int foo(int i) {
return 5*i;
}
};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
不过,让我们假设您确实想要拥有非静态成员函数。为此,让我们为A 类型添加一点状态:
struct A {
A(int f) : f_(f) {}
int foo(int i) { return f_*i; }
private:
int f_;
};
Phoenix 提供以下方法来创建调用成员函数的惰性 Actor:
-
使用->* 运算符。这会导致语法有点晦涩:
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7); // direct == 63
-
或者,您可以使用 bind 表达式(注意:boost::phoenix::bind 此处!),这可能正是您要查找的内容:
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
现在,当然,您可能希望将惰性函子分配给一个变量。这方面我只能推荐BOOST_AUTO:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
这就像一个魅力。
完整的 C++03 示例
看Live on Coliru
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <cassert>
int main() {
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7);
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
assert(direct == with_bind);
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
}