[英]C++ Dynamically Define Function
I am on visual c++ working on a console calculator, I am creating a way to let the user define a custom linear function. 我正在使用Visual C ++在控制台计算器上工作,正在创建一种让用户定义自定义线性函数的方法。 Here is where I am stumped: Once I get the users desired name of the function, the slope, and the y-intercept, I need to use that data to create a callable function that I can pass to muParser.
这是让我感到困惑的地方:一旦获得用户所需的函数名称,斜率和y轴截距,我就需要使用该数据来创建可调用函数,然后将其传递给muParser。
In muParser, you define custom functions like this: 在muParser中,您可以这样定义自定义函数:
double func(double x)
{
return 5*x + 7; // return m*x + b;
}
MyParser.DefineFun("f", func);
MyParser.SetExpr("f(9.5) - pi");
double dResult = MyParser.Eval();
How could I dynamically create a function like this based on the users input for the values 'm' and 'b' and pass that to the 'DefineFun()' method? 如何根据用户输入的值“ m”和“ b”动态创建类似这样的函数,并将其传递给“ DefineFun()”方法? This is what I have so far:
这是我到目前为止的内容:
void cb_SetFunc(void)
{
string FuncName, sM, sB;
double dM, dB;
bool GettingName = true;
bool GettingM = true;
bool GettingB = true;
regex NumPattern("[+-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?");
EchoLn(">>> First, enter the functions name. (Enter 'cancel' to abort)");
EchoLn(">>> Only letters, numbers, and underscores can be used.");
try
{
do // Get the function name
{
Echo(">>> Enter name: ");
FuncName = GetLn();
if (UserCanceled(FuncName)) return;
if (!ValidVarName(FuncName))
{
EchoLn(">>> Please only use letters, numbers, and underscores.");
continue;
}
GettingName = false;
} while (GettingName);
do // Get the function slope
{
Echo(">>> Enter slope (m): ");
sM = GetLn();
if (UserCanceled(sM)) return;
if (!regex_match(sM, NumPattern))
{
EchoLn(">>> Please enter any constant number.");
continue;
}
dM = atof(sM.c_str());
GettingM = false;
} while (GettingM);
do // Get the function y-intercept
{
Echo(">>> Enter y-intercept (b): ");
sB = GetLn();
if (UserCanceled(sB)) return;
if (!regex_match(sB, NumPattern))
{
EchoLn(">>> Please enter any constant number.");
continue;
}
dB = atof(sB.c_str());
GettingB = false;
} while (GettingB);
// ------------
// TODO: Create function from dM (slope) and
// dB (y-intercept) and pass to 'DefineFun()'
// ------------
}
catch (...)
{
ErrMsg("An unexpected error occured while trying to set the function.");
}
}
I was thinking that there isn't a way to define an individual method for each user-defined-function. 我当时在想,没有一种方法可以为每个用户定义的函数定义一个单独的方法。 Would I need to make a
vector<pair<double, double>> FuncArgs;
我需要做一个
vector<pair<double, double>> FuncArgs;
to keep track of the appropriate slopes and y-intercepts then call them dynamically from the function? 跟踪适当的斜率和y轴截距,然后从函数中动态调用它们? How would I specify which pair to use when I pass it to
DefineFun(FuncStrName, FuncMethod)
? 将其传递给
DefineFun(FuncStrName, FuncMethod)
时,如何指定要使用的一对?
What you need (in addition to a script language interpreter) is called a "trampoline" . 您需要的(除了脚本语言解释器之外)被称为“蹦床” 。 There is no standard solution to create those, in particular since it involves creating code at runtime.
没有标准的解决方案来创建这些代码,特别是因为它涉及在运行时创建代码。
Of course, if you accept a fixed number of trampolines, you can create them at compile time. 当然,如果您接受固定数量的蹦床,则可以在编译时创建它们。 And if they're all linear, this might be even easier:
如果它们都是线性的,则可能会更容易:
const int N = 20; // Arbitrary
int m[N] = { 0 };
int b[N] = { 0 };
template<int I> double f(double x) { return m[I] * x + b; }
This defines a set of 20 functions f<0>...f<19>
which use m[0]...m[19]
respectively. 这定义了一组20个函数
f<0>...f<19>
,分别使用m[0]...m[19]
。
Edit: 编辑:
// Helper class template to instantiate all trampoline functions.
double (*fptr_array[N])(double) = { 0 };
template<int I> struct init_fptr<int I> {
static const double (*fptr)(double) = fptr_array[I] = &f<I>;
typedef init_fptr<I-1> recurse;
};
template<> struct init_fptr<-1> { };
GiNaC是C ++库,可以解析和评估数学表达式。
Try to embed to your application some script language. 尝试将一些脚本语言嵌入到您的应用程序中。 Years ago I was using Tcl for similar purpose - but I do not know what is the current time best choice.
多年前,我将Tcl用于类似目的-但我不知道当前最好的选择是什么。
Either you can start from Tcl or search yourself for something better: 您可以从Tcl开始,也可以自己搜索更好的东西:
See: Adding Tcl/Tk to a C application 请参阅: 将Tcl / Tk添加到C应用程序
I would keep it simple: 我会保持简单:
#include <functional>
std::function<double(double)> f; // this is your dynamic function
int slope, yintercept; // populate from user input
f = [=](double x) -> double { return slope * x + yintercept; };
Now you can pass the object f
to your parser, which can then call f(x)
at its own leisure. 现在,您可以将对象
f
传递给解析器,然后解析器可以随意调用f(x)
。 The function object packages the captured values of slope
and yintercept
. 函数对象打包捕获的
slope
和yintercept
值。
Generating a fixed array of functions bindable to boost function. 生成可绑定到boost功能的固定功能数组。
Someone else already said about a similar method, but since I'd taken the time to write the code, here it is anyway. 有人已经说过类似的方法,但是由于我花了一些时间编写代码,所以还是可以的。
#include <boost/function.hpp>
enum {
MAX_FUNC_SLOTS = 255
};
struct FuncSlot
{
double (*f_)(double);
boost::function<double(double)> closure_;
};
FuncSlot s_func_slots_[MAX_FUNC_SLOTS];
template <int Slot>
struct FuncSlotFunc
{
static void init() {
FuncSlotFunc<Slot-1>::init();
s_func_slots_[Slot - 1].f_ = &FuncSlotFunc<Slot>::call;
}
static double call(double v) {
return s_func_slots_[Slot - 1].closure_(v);
}
};
template <> struct FuncSlotFunc<0> {
static void init() {}
};
struct LinearTransform
{
double m_;
double c_;
LinearTransform(double m, double c)
: m_(m)
, c_(c)
{}
double operator()(double v) const {
return (v * m_) + c_;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
FuncSlotFunc<MAX_FUNC_SLOTS>::init();
s_func_slots_[0].closure_ = LinearTransform(1, 0);
s_func_slots_[1].closure_ = LinearTransform(5, 1);
std::cout << s_func_slots_[0].f_(1.0) << std::endl; // should print 1
std::cout << s_func_slots_[1].f_(1.0) << std::endl; // should print 6
system("pause");
return 0;
}
So, you can get the function pointer with: s_func_slots_[xxx].f_ And set your action with s_func_slots_[xxx].closure_ 因此,您可以使用以下命令获取函数指针:s_func_slots_ [xxx] .f_并使用s_func_slots_ [xxx] .closure_设置操作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.