Starting with the simplest:
How come it doesn't just work like in bind and function?
Because the macro is designed for functions, not member functions. Pointer-to-member-functions are very different from function pointers, so that's the end of the road.
In your example, A::foo
doesn't actually need to be an instance method (non-static member function), so just add static
(and an implicit parameter) and be done:
struct A {
static int foo(int i) {
return 5*i;
}
};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
Let's assume, though, that you did want to have the non-static member function. For this reason, let's add a little state to the A
type:
struct A {
A(int f) : f_(f) {}
int foo(int i) { return f_*i; }
private:
int f_;
};
Phoenix provides the following approaches to create lazy actors calling member functions:
use the ->*
operator. This leads to slightly obscure syntax:
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7); // direct == 63
alternatively, you can use a bind
expression (note: boost::phoenix::bind
here!), which might just be what you were looking for:
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
Now, of course, you might be looking to assign the lazy functor to a variable. In that respect, I can only recommend BOOST_AUTO
:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
Which works like a charm.
Full C++03 Sample
See it 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);
}