Evaluating a run-time constructed function is not going to be “quick” in any reasonable sense of the word, unless you go full out and compile it, e.g. to a dynamic library.
Barring that you can just construct a dynamic expression tree.
You will probably want to add a bit of syntactic sugar compared to the code below, but it shows the basics:
#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;
}