Interface problem

S

StephQ

I'm writing some algorithms that works on generic functions using
boost::bind.
My problem is that class templates can never be deduced.

In the simplest cases I just write the class like:

class Legendre
{
....
public:
template<class F>
static double computeIntegral( const F& f );
}

double value = Legendre::computeIntegral(boost::bind( &Sde::drift,
&sde, _1 ));

However in more complext examples, I have to work with classes with
non static memeber fucntions.
For example becouse I need to store data previously calculated about
the function for efficecny reasons.
I would like to "fix" the F at the moment of the construction of the
class and then invoke member functions of the class to perform
operations.

That is I would like to being able to do something like:

template<class F>
class FunctionAnalysis
{
private:

F& function;

public:
FunctionAnalysis( const F& f );

double operation1();
double operation2();
}

template<class F>
FunctionAnalysis<F>::FunctionAnalysis( const F& f)
:
function(f)
{}

FunctionAnalysis driftAnalysis(boost::bind( &Sde::drift, &sde, _1 ));
double x = driftAnalysis.operation1();
double y = driftAnalysis.operation2();

There are two problems:
1) I class template arguments can never be deduced
2) driftAnalysis is not of type FunctionAnalysis

I can solve the fist problem using the same approach of make_pair, but
I dont't see any way to solve th second problem.

The objective is to avoid having to specify the template parameter of
the class (and using boos::bind you can easily see why :D ).

Do you have any suggestion?

Thank you!

Cheers
StephQ
 
W

witkamp

Problem 1.
Only template functions can deduce types from an argument list. This
excludes C++ constructors!
The common solution for this is a make_function() template function.
Example:

template<typename T>
FunctionAnalysis<T> make_analysis(const T& func)
{
return FunctionAnalysis<T>(func);
}

Problem 2.
You are using a template with out template parameters. It needs to be
some thing more like this

typedef boost::bind( &Sde::drift, &sde, _1 )::type;
FunctionAnalysis<T> driftAnalysis(boost::bind( &Sde::drift, &sde,
_1 ));

But this is no fun.


You should really not pass boost::bind types into template parameters
like this. Here is what I would propose.

Alternate Solution

class FunctionAnalysis
{
private:
boost::function<double(double)> function;

public:
FunctionAnalysis(boost::function<double(double)> f );
double operation1();
double operation2();
}

// use it like this without any trouble

FunctionAnalysis driftAnalysis(boost::bind( &Sde::drift, &sde, _1 ));
double x = driftAnalysis.operation1();
double y = driftAnalysis.operation2();
 
S

StephQ

Only template functions can deduce types from an argument list. This
excludes C++ constructors!
The common solution for this is a make_function() template function.
Example:

template<typename T>
FunctionAnalysis<T> make_analysis(const T& func)
{
return FunctionAnalysis<T>(func);

}

Eaxctly what I was saying abaout make_pair.
Problem 2.
You are using a template with out template parameters. It needs to be
some thing more like this

typedef boost::bind( &Sde::drift, &sde, _1 )::type;
FunctionAnalysis<T> driftAnalysis(boost::bind( &Sde::drift, &sde,
_1 ));

But this is no fun.

I agree :)
You should really not pass boost::bind types into template parameters
like this. Here is what I would propose.

Alternate Solution

class FunctionAnalysis
{
private:
boost::function<double(double)> function;

public:
FunctionAnalysis(boost::function<double(double)> f );
double operation1();
double operation2();

}

// use it like this without any trouble

FunctionAnalysis driftAnalysis(boost::bind( &Sde::drift, &sde, _1 ));
double x = driftAnalysis.operation1();
double y = driftAnalysis.operation2();

Thank you very much, it's excactly what I was searching for.
I just ignored the existance of boost::function.

Cheers
StephQ
 
S

StephQ

I just run in the following problem.
I'm using the gsl library that requires an input function to be of the
form:

struct gslFunction
{
double (*func)(double x, void* p) function;
void* params;
}


To be able to interface to the gsl I wrote this "converter" (based on
root's mathmore library gsl wrapper):


// Use in combination with boost::bind.
template<class F>
static double gslFunctionAdapter( double x, void* p)
{
// Here I do recover the "right" pointer, safer to use static_cast
than reinterpret_cast.
F* function = static_cast<F*>( p );
return (*function)( x );
}

template<class F>
gsl_function convertToGslFunction( const F& f )
{
gsl_function gslFunction;

const void* p = &f;
assert (p != 0);

gslFunction.function = &gslFunctionAdapter<F>;
gslFunction.params = const_cast<void*>( p ); // Just to eliminate
the const.

return gslFunction;
}

and use this like:
gslFunction gslF = convertToGslFunction( boost::bind( &Sde::drift,
&sde, _1 ) );

However the problem is that now I'm using boost::function in my
algorithms, following your suggestion.
So in an algorithm I get into the situation:

boost::function<double (double)> f = boost::bind( &Sde::drift, &sde,
_1 );
gslFunction gslF = convertToGslFunction( f );

I know that this "double-wrapper" is bad for efficency, but I can't
see any other way to use the gsl library without modification on the
gsl library itself.
The problem is that this does not work! When I call the gslF the
software crash.
Debugger inspection reveals that the line:

F* function = static_cast<F*>( p ); // in gslFunctionAdapeter

fails to "recover" my boost::funcion.

Is there anything I could do to solve the situation?

The two requirements are:

1) Be able to implement the approach suggested in the post above: that
is have boost::function private member data in my algorithms

2) Interface to the gslFunction struct without any modification to the
gsl library.

Thank you again for your help.

Best Regards
StephQ
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top