Могу ли я передать функцию-член в mu :: Parser :: DefineFun ()?

я использую muParser для синтаксического анализа математических выражений, и я хотел бы добавить функцию в синтаксический анализатор, реализация которой будет обеспечиваться нестатической функцией-членом класса. Этот отрывок из пример программы должен дать представление о том, что я хочу сделать:

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 может иметь любую из следующих сигнатур функций:

  • double f()
  • double f(double)
  • double f(double, double)
  • и так далее до 10 double аргументы
  • 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Мне кажется, что мне нужна связанная функция, и предпочтительный способ сделать это (в 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в то время как мне нужна стандартная функция, и в соответствии с этот ответ более или менее невозможно получить стандартную функцию от boost::function без некоторых void* спрятать указатель экземпляра. Но я не уверен, что правильно понимаю, имея небольшой опыт работы с Boost, поэтому мой предварительный вопрос: может ли кто-нибудь подтвердить, что boost::bind просто не буду делать то, что мне нужно сделать?

И мой главный вопрос: есть ли любой способ вообще сделать это? Даже если это связано с тайными секретами волшебства C ++? (Или же *удушье* переход на C ++ 11?)

1

Решение

Похоже, API muParser, к сожалению, не готов к C ++.

В C ++ 11 Lambdas может «разлагаться», чтобы функционировать указатели, но это означает, что они должны быть без состояний, поэтому вы возвращаетесь в одно и то же место: вы не можете связывать дополнительные параметры.

Является ли muParser открытым исходным кодом? Возможно, есть вилка, которая уже исправила этот недостаток дизайна


О да, да, boost::bind не могу нарушать законы физики сделай это для тебя

3

Другие решения


По вопросам рекламы [email protected]