Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing expression template functors

at the moment I'm really interested in expression templates and want to code a library for writing and differentiating mathematical functions with a lambda-style syntax. At the moment, I'm able to write (_x * _x)(2); and get the correct result 4. But I would really like to do something like MathFunction f = _x * _x; f(2);, but I don't have any ideas on how to cope with the recursive expression templates on the right side. Is it possible to achieve this without using the 'auto'-Keyword instead of MathFunction or having to make the operator() virtual?

Thanks for your help!

like image 460
Fabian Meumertzheim Avatar asked Mar 19 '10 10:03

Fabian Meumertzheim


3 Answers

.

template<class T, class R>
struct MathFuncBase
{
   virtual R operator()(const T & v) = 0;
   virtual ~MathFuncBase() {}
};

tempate<class T, class R, class Func>
struct MathFunc : MathFuncBase<T, R>
{
   MathFunc(Func func) : func(func) {}
   virtual R operator()(const T & v) {
       return func(v);           
   }
private:
   Func func;
};

tempate<class T, class R, class Func>
boost::shared_ptr<MathFuncBase<T, R> > GetMathFunc(Func func) {
    return boost::shared_ptr<MathFuncBase<T, R> >(new MathFunc<T, R, Func> (func));
}

int main () {
    boost::shared_ptr<MathFuncBase<int, int> > f = GetMathFunc<int,int> (_x * _x);
    return (*f)(2);   
}
like image 118
Alexey Malistov Avatar answered Sep 24 '22 06:09

Alexey Malistov


Well, Boost already supports this functionality already, so you may want to take a look at how they have done it.

The following links were really helpful when I was learning:
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Expression-template
http://www.angelikalanger.com/Articles/Cuj/ExpressionTemplates/ExpressionTemplates.htm http://www.flipcode.com/archives/Faster_Vector_Math_Using_Templates.shtml

The second link is my personal favourite!

All the best.

like image 24
batbrat Avatar answered Sep 24 '22 06:09

batbrat


Actually I don't think there is a simple way to store them. If I wanted to create a named instance of boost::lambda expression, I would assign the result to, say, int and then copy the name of the needed type from the compiler's error message:

#include <boost/lambda/lambda.hpp>

int main()
{
    using namespace boost::lambda;
    //int x = _1 + _2;
    boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<
    boost::lambda::arithmetic_action<boost::lambda::plus_action>, 
    boost::tuples::tuple<boost::lambda::lambda_functor<boost::lambda::placeholder<1> >, 
    boost::lambda::lambda_functor<boost::lambda::placeholder<2> >, 
    boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, 
    boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, 
    boost::tuples::null_type, boost::tuples::null_type> > > x = _1 + _2;
}

In real life you'd be more likely to store them in a type, that does type erasure, like boost::function.

#include <boost/lambda/lambda.hpp>
#include <boost/function.hpp>   
int main()
{
    using namespace boost::lambda;
    boost::function<int(int, int)> x = _1 + _2;
    return x(-1, 1);
}
like image 43
visitor Avatar answered Sep 22 '22 06:09

visitor