Reputation: 36451
https://gist.github.com/2934374
So I was intrigued by this comparison and also by the awful C++ solutions that appeared in the comments, but I must admit I'm having trouble to write a nice solution myself :-)
My current attempt looks like this, the problems are:
So how could I squish it a bit and bind the variables so they would be affected by changes?
#include <map>
#include <string>
#include <iostream>
#include <functional>
using namespace std;
/* environ */
map<string,int> variables = { { "a" , 3 }, { "b", 4 }, { "c", 5 } };
function<int(int,int)> add = [] (int lp, int rp) { return lp + rp; };
function<int(int,int)> mlt = [] (int lp, int rp) { return lp * rp; };
/* impl */
struct Var {
Var(int v) : p_v(v) {};
int eval() { return p_v; };
private:
int p_v;
};
template <typename LP, typename RP>
struct Op {
Op(function<int(int,int)> op, LP lp, RP rp) : p_op(op), p_l(lp), p_r(rp) {};
int eval() { return p_op(p_l.eval(), p_r.eval()); }
private:
function<int(int,int)> p_op;
LP p_l;
RP p_r;
};
Var var(int val) { return Var(val); }
template <typename LP, typename RP>
auto op(function<int(int,int)> op, LP lp, RP rp) -> Op<LP,RP>
{
return Op<LP,RP>(op,lp,rp);
}
Var operator "" _var(const char *key, size_t length)
{ return Var(variables[key]); }
/* gcc is failing me
Var operator "" _num(int val)
{ return Var(val); }
*/
int main()
{
auto tree = op ( add, "a"_var, op ( mlt, var ( 2 ), "b"_var ));
cout << tree.eval() << endl;
}
Upvotes: 0
Views: 427
Reputation: 147036
You're re-inventing the Standard bind mechanism. There's no need for any glue code to be written by the user.
auto tree = bind(plus<int>(), ref(variables["a"]), bind(multiplies<int>(), 2, ref(variables["b"])));
cout << tree();
http://liveworkspace.org/code/f06fd83b5d7bcbf4829306d4e590da38
std::ref
makes it a reference, not a value- this means that you could bind a mutating operation.
Upvotes: 3