我正在使用muParser解析数学表达式,我想向解析器添加一个函数,其实现将由类的非静态成员函数提供。此摘录自an example program应该告诉我我想做什么:
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;
}
其中 MORE_MAGIC(...)
代表具有签名 double f(double arg1, double arg2)
的内容,相当于调用 instance-> make_a_value(arg1,arg2)
。我不知道 MORE_MAGIC
应该是什么才能使其发挥作用。这就是我问题的本质。
DefineFun
的第二个参数可以具有以下任意函数签名:
双 f()
双 f(双)
双 f(双, 双)
- 依此类推,最多 10 个
双
参数 double f(double*, int)
其中第一个指针是数组,int
是其长度double f(const char*)
double f(const char*, double)
double f(const char*, double)
不幸的是,这些都不包含我可以用来传递实例的 void*
数据参数。我想到要颠覆一个 double* 来传递实例,但问题实际上是 muParser 根本不允许我预先定义要传递给函数的值;仅传递从解析表达式中获取的参数。
通过阅读其他几篇文章( 1 、 2 、 3 、 4 、 5 ),我似乎需要的是一个绑定(bind)函数,以及执行此操作的首选方法(在 C 中)++98) 是 boost::bind
。但我尝试将 MORE_MAGIC(...)
替换为 boost::bind(&wrapper, _1, _2, &instance)
,以及
double wrapper(double a, double b, MyClass* p) {
return p->make_a_value(a, b);
}
(希望语法正确)并且我收到编译器错误:
/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() );
等等。恶心。
我猜问题是 boost::bind
返回一个 boost::function
,而我需要一个标准函数,并且根据 this answer如果没有一些 void*
来存储实例指针,从 boost::function
获取标准函数或多或少是不可能的。但我不确定我的理解是否正确,因为对 Boost 的经验很少,所以我的初步问题是:任何人都可以确认 boost::bind
只是不会我需要它做什么?
我的主要问题是:是否有任何方法可以实现这一目标?即使它涉及 C++ 魔法的神秘 secret ? (或者*喘息*切换到C++11?)
最佳答案
遗憾的是,muParser API 似乎还没有为 C++ 做好准备。
在 C++11 中,Lambda 可以“衰减”为函数指针,但这意味着它们必须是无状态的,因此,您又回到了同样的情况:无法绑定(bind)额外的参数。
muParser 是开源的吗?也许有一个 fork 已经修正了这个设计缺陷
哦,是的,boost::bind
不能打破物理定律 为你做到这一点
关于c++ - 我可以将成员函数传递给 mu::Parser::DefineFun() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27088272/