C++动态定义函数
C++ Dynamically Define Function
我在visual c++上开发控制台计算器,我正在创建一种让用户定义自定义线性函数的方法。这就是我的困惑所在:一旦我得到了用户想要的函数名称、斜率和y截距,我就需要使用这些数据来创建一个可调用的函数,我可以将其传递给muParser。
在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();
如何根据用户输入的值"m"answers"b"动态创建这样的函数,并将其传递给"DefineFun()"方法?这就是我目前所拥有的:
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.");
}
}
我在想,没有办法为每个用户定义的函数定义一个单独的方法。我是否需要制作一个vector<pair<double, double>> FuncArgs;
来跟踪适当的斜率和y截距,然后从函数中动态调用它们?当我将其传递给DefineFun(FuncStrName, FuncMethod)
时,我将如何指定要使用哪对?
您需要的(除了脚本语言解释器)被称为"蹦床"。没有创建这些代码的标准解决方案,特别是因为它涉及在运行时创建代码。
当然,如果您接受固定数量的蹦床,您可以在编译时创建它们。如果它们都是线性的,这可能会更容易:
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; }
这定义了一组20个函数f<0>...f<19>
,它们分别使用m[0]...m[19]
。
编辑:
// 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> { };
我会保持简单:
#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; };
现在,您可以将对象f
传递给解析器,然后解析器可以在空闲时调用f(x)
。函数对象封装捕获的slope
和yintercept
的值。
GiNaC是C++库,可以解析和计算数学表达式。
生成可绑定到boost函数的固定函数数组。
其他人已经说过类似的方法,但由于我花了一些时间编写代码,所以它就在这里。
#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;
}
因此,您可以使用:s_func_slots_[xxx].f获得函数指针_并使用s_func_slots_[xxx].closure_
尝试在应用程序中嵌入一些脚本语言。几年前,我也曾出于类似的目的使用Tcl,但我不知道目前的最佳选择是什么。
要么你可以从Tcl开始,要么自己搜索更好的东西:
请参阅:将Tcl/Tk添加到C应用程序
- 不同翻译单元中不可重载的非内联函数定义
- Visual Studio中的函数声明和函数定义问题
- 编写代码时C++出现错误:错误 1 错误 C2601:'circle':本地函数定义是非法的
- 具有enable_if外部类原型的模板类构造函数定义
- 类的前向声明之后的类成员函数定义,在类声明之前
- 为函数定义符号不明确的指针参数
- C++模板专用化 - 无法匹配函数定义
- 错误:在第 6 行'{'标记之前,此处不允许使用函数定义
- 找不到 #define 的函数定义
- 根据类型特征更改函数定义?
- 将抽象基类中的所有纯虚函数定义为 varaidaic 模板
- 命名空间更改函数定义
- "Type&"与C++函数定义中的"Type*"
- C++:为什么允许在另一个函数中声明函数,而不允许在函数定义中声明?
- 如何从 C++ 中的现有模板函数定义新函数
- 私有在函数定义/实现的返回值范围内是什么意思 (c++)?
- 越界成员函数定义是否需要一个完全限定的类名,直到全局范围
- 为什么c++允许成员函数定义中实例的私有成员访问
- Qt基类函数定义
- C++函数定义中参数列表后面额外一对括号的含义