假设我有一些用C ++编写和编译的函数:
int quicksum(int a, int b){ return a+b; }
int quickmult(int a, int b){ return a*b; }
在运行时,我希望能够创建这些函数的组合,例如quicksum(quickmult(5,6),7)
,并将其保存为我可以随时执行的已保存过程。
目前,我已经在Qt中使用JavaScript和C ++一半了,其中quicksum
等函数在C ++中定义,然后通过执行此操作从JavaScript调用:
var somestring="quicksum(5,(quicksum(4,4)))"
eval(somestring)
现在这样可行,但问题是这些函数的组合仍在JavaScript端进行管理,这意味着JS在将其输入到另一个函数之前处理来自一个函数的返回,而不是运行整个函数的C ++组合本身(至少我认为是这样)。
我不介意在JS中创建初始组合,但出于性能原因,我不希望每次需要调用函数组合时都涉及JS。
有没有办法以某种方式将这些功能组合放到C ++端并让它留在那里以便以后运行?我不介意把JS完全带出这个过程,这只是我能想到的唯一方法;也许有一些聪明的方法在C ++中使用仿函数在运行时动态拼接已经编译过的函数?
...更新
我正在考虑的另一个选择是使用本身具有引用其他仿函数的成员变量的仿函数。如果JS调用带有其他仿函数参数的仿函数构造函数,这有点像在运行时使用闭包创建一个新函数。然后这个仿函数将完全是一个C ++对象,其中存储过程(我认为)。我需要在脑子里解决这个问题。
答案 0 :(得分:3)
评估运行时构造的函数在任何合理的意义上都不会“快速”,除非你全力以赴并编译它,例如到动态图书馆。
除非您可以构建动态表达式树。
与下面的代码相比,您可能希望添加一些语法糖,但它显示了基础知识:
#include <iostream>
#include <functional> // std::plus, std::multiplies
#include <memory> // std::unique_ptr
#include <utility> // std::move
using namespace std;
struct Expression
{
virtual auto eval() const -> double = 0;
virtual ~Expression() {}
};
struct Number: Expression
{
double value;
auto eval() const -> double override { return value; }
Number( double v ): value( v ) {}
};
struct Binary_op: Expression
{
unique_ptr<Expression> a;
unique_ptr<Expression> b;
Binary_op( unique_ptr<Expression> _a, unique_ptr<Expression> _b )
: a( move( _a ) ), b( move( _b ) )
{}
};
template< class Impl >
struct Concrete_binary_op: Binary_op
{
auto eval() const -> double override
{ return Impl()( a->eval(), b->eval() ); }
Concrete_binary_op( unique_ptr<Expression> _a, unique_ptr<Expression> _b )
: Binary_op( move( _a ), move( _b ) )
{}
};
using Sum = Concrete_binary_op<std::plus<double>>;
using Product = Concrete_binary_op<std::multiplies<double>>;
auto number( double v )
-> unique_ptr<Number>
{ return unique_ptr<Number>( new Number( v ) ); }
auto sum( unique_ptr<Expression> a, unique_ptr<Expression> b )
-> unique_ptr<Sum>
{ return unique_ptr<Sum>( new Sum( move( a ), move( b ) ) ); }
auto product( unique_ptr<Expression> a, unique_ptr<Expression> b )
-> unique_ptr<Product>
{ return unique_ptr<Product>( new Product( move( a ), move( b ) ) ); }
auto main()
-> int
{
auto e = sum( product( number( 5 ), number( 6 ) ), number( 7 ) );
cout << e->eval() << endl;
}