Boost logo

Boost Users :

From: jhr.walter_at_[hidden]
Date: 2003-03-08 06:11:25


Hi Roland,

you wrote:

> > > If the constructor also would accept a row I could use it as a
> > > parameter type for function calls when I want to express, that
> > > only 'data' types are expected and 'expressions' are not wanted.
> > > (Sorry for the sloppy formulation, I am not sure how to express
> > > this more concise.)
> >
> > I hope, we'll be able to solve this, too.
>
> Finally I found a solution that works with expressions, without the
> burden of template parameter specification. I took up your suggestion
> and blended it with boost::function. I would be glad if you could
> have a look on it and perhaps comment.
>====================================================================
> #include <iostream>
> #include <boost/numeric/ublas/config.hpp>
> #include <boost/numeric/ublas/vector.hpp>
> #include <boost/numeric/ublas/matrix.hpp>
> #include <boost/numeric/ublas/io.hpp>
> #include <boost/function.hpp>
> using namespace boost::numeric::ublas;
>
> // this is the class that implements the functor
> // it also could be parameterized on more than one expression
> // (this is what Joerg suggested)
> template<class T, class E>
> class func_impl {
> public:
> func_impl(const vector_expression<E> &e) : e_ (e) {}

    func_impl(const vector_expression<E> &e) : e_ (e ()) {}

> T operator() (const T& x){
> // algorithm goes here ...
> return e_()(0)*x; // just for demonstration
> }
> private:
> const vector_expression<E> &e_;

// Storing the closure type should prevent some subtle lifetime issues
// when chaining functions for example...
typename E::const_closure_type e_;

> };
>
> // this is the user part of the functor
> // the constructor is used to act as a generator for the
> // implementation type.
> template<class T>
> class func : public boost::function1<T, T> {
> public:
> template<class E>
> func(const vector_expression<E>& e)
> : boost::function1<T, T>(func_impl<T, E>(e)) {}
> };
>
>
> int main(int argc, char* argv[])
> {
> matrix<double> m (3,3);
> vector<double> v (3);
> func<double> f(m.row(0)); // notice: no need to know the type of m.row
>
> m(0,0) = 0.0; m(0,1) = 0.1; m(0,2) = 0.2;
> m(1,0) = 1.0; m(1,1) = 1.1; m(1,2) = 1.2;
> m(2,0) = 2.0; m(2,1) = 2.1; m(2,2) = 2.2;
>
> std::cout << f(1.0) << std::endl;
> // outputs: 0
>
> m(0,0) = 47.11; // change the referenced matrix
> std::cout << f(1.0) << std::endl;
> // outputs: 47.11
>
> // other argument types ...
> func<double> f1(m.column(2));
> std::cout << f1(1.0) << std::endl;
> // outputs: 0.2
> m(0,2) = 13;
> std::cout << f1(1.0) << std::endl;
> // outputs: 13
>
> // similar with vector ...
> func<double> f2(v);
>
> return 0;
> }
>====================================================================
>
> Of course this involves an indirection since I am using the
> functiom.hpp from boost as base class. But I think this is not
> avoidable in principle, since this is what a reference is all about,
> isn't it?

Impressed-by-this-nice-combination-of-different-libraries-ly y'rs

Joerg


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net