Хранение функторов шаблонов выражений - PullRequest
5 голосов
/ 19 марта 2010

на данный момент я действительно заинтересован в шаблонах выражений и хочу написать библиотеку для написания и дифференцирования математических функций с использованием синтаксиса в стиле лямбда-выражения. На данный момент я могу написать (_x * _x)(2); и получить правильный результат 4. Но я бы очень хотел сделать что-то вроде MathFunction f = _x * _x; f(2);, но у меня нет никаких идей о том, как справиться с рекурсивными шаблонами выражений на правой стороне. Возможно ли достичь этого, не используя ключевое слово auto вместо MathFunction или сделав оператор () виртуальным?

Спасибо за вашу помощь!

Ответы [ 5 ]

3 голосов
/ 19 марта 2010

.

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);   
}
1 голос
/ 19 марта 2010

На самом деле я не думаю, что есть простой способ их хранения. Если бы я хотел создать именованный экземпляр выражения boost :: lambda, я бы присвоил результат, скажем, int , а затем скопировал имя нужного типа из сообщения об ошибке компилятора:

#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;
}

В реальной жизни вы, скорее всего, будете хранить их в типе, который стирает тип, например 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);
}
1 голос
/ 19 марта 2010

Ну, Boost уже поддерживает эту функцию, так что вы можете посмотреть, как они это сделали.

Следующие ссылки были действительно полезны, когда я учился:
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

Вторая ссылка - моя любимая!

Всего наилучшего.

0 голосов
/ 19 марта 2010

Поскольку я новичок в этом сайте, я нашел это только после того, как отправил вопрос Спасибо за ваши ответы, но это то, что я действительно искал.

0 голосов
/ 19 марта 2010

Я сомневаюсь, что это возможно без виртуальной функции. Вам нужно выполнить стирание типа, поскольку вы не можете использовать auto и аналогичные. Но позже в этой области, поскольку вы вызываете функцию для типа стираемого объекта, вам необходима поддержка во время выполнения для вызова функции из производного объекта класса.

Я подозреваю, что без auto ты не сможешь это сделать.

...