I'm using muParser to parse mathematical expressions, and I would like to add a function to the parser whose implementation will be provided by a non-static member function of a class. This excerpt from an example program should give an idea of what I want to do:
struct MyClass { // some boilerplate omitted
double make_a_value(double a, double b); // implemented elsewhere
};
int main(const int argc, const char** argv) {
MyClass instance;
mu::Parser p;
p.DefineFun("f", MORE_MAGIC(MyClass::make_a_value, &instance));
p.SetExpr("f(3, 2)");
std::cout << p.Eval() << std::endl;
}
where MORE_MAGIC(...)
stands for something with the signature double f(double arg1, double arg2)
which is equivalent to calling instance->make_a_value(arg1, arg2)
. I don't know what MORE_MAGIC
should be in order for this to work. That's the essence of my question.
The second argument of DefineFun
can have any of the following function signatures:
double f()
double f(double)
double f(double, double)
- and so on up to 10
double
arguments double f(double*, int)
where the first pointer is an array and theint
is its lengthdouble f(const char*)
double f(const char*, double)
double f(const char*, double)
Unfortunately none of these include a void*
data parameter that I can use to pass in an instance. It occurred to me to subvert a double*
to pass the instance, but the problem is really that muParser doesn't let me pre-define a value to be passed to the function at all; only the arguments taken from the parsed expression get passed.
From reading several other posts (1, 2, 3, 4, 5) t seems that what I need is a bound function, and the preferred way to do it (in C++98) is boost::bind
. But I've tried replacing MORE_MAGIC(...)
with boost::bind(&wrapper, _1, _2, &instance)
, with
double wrapper(double a, double b, MyClass* p) {
return p->make_a_value(a, b);
}
(hopefully correct syntax) and I get compiler errors:
/usr/include/muParserBase.h:134:95: error: no matching function for call to ‘mu::ParserCallback::ParserCallback(boost::_bi::bind_t<double, double (*)(double, double, MyClass*), boost::_bi::list3<boost::arg<1>, boost::arg<2>, boost::_bi::value<MyClass*> > >&, bool&)’
AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), m_FunDef, ValidNameChars() );
and so on. Ick.
I guess the problem is that boost::bind
returns a boost::function
, whereas I need a standard function, and according to this answer it's more or less impossible to get a standard function from a boost::function
without some void*
to stash the instance pointer. But I'm not sure I'm understanding correctly, having little experience with Boost, so my preliminary question is: can anyone confirm that boost::bind
simply will not do what I need it to do?
And my main question: is there any way at all to accomplish this? Even if it involves arcane secrets of C++ wizardry? (Or *gasp* switching to C++11?)
Looks like the muParser API sadly isn't ready for C++.
In C++11 Lambdas can "decay" to function pointers, but this means they have to be stateless, so, you're back at the same spot: you can't bind extra parameters.
Is muParser open source? Perhaps there is a fork that has already amended this design flaw
Oh and, yes,
boost::bind
cannotbreak the laws of physicsdo this for you