Register to reply

[C++] Pointers to member functions

by Wallace
Tags: functions, member, pointers
Share this thread:
Wallace
#1
May18-08, 09:33 PM
Sci Advisor
P: 1,253
Hi, I was hoping a C++ guru could help me with a problem I'm having using the gnu science library (gsl) in my C++ code. Here is my issue:

Take for instance the Runge Kutter codes for solving differential equations. You need to supply the gsl routines for this a pointer to a function describing the derivatives of the system. In many cases I would like this function to be a member function of some class I have defined. However, since pointers to member functions are not the same as pointers to functions, when I try and do this I get an error.

This is annoying as it means all of these functions have to sit outside classes and especially annoying as these functions need to access many members of the classes they would ideally be members of in working out the derivatives. At present I need to use variables of global scope in order to get information into these functions which is annoying and ugly in a C++ context.

What I would love to know is how to make the gsl routines accept pointers to member functions, if this is at all possible. I know enough about this issue to realise what is causing the error when I give the gsl routines a pointer to a member function, but I have no idea how to resolve this issue, if it is even possible, which I certainly hope it is!

To be clear, here is a concrete example of my problem. Take the example ODE code here. The stepper function needs an object 'sys' defined by

gsl_odeiv_system sys = {func, jac, 2, &mu};

where func and jac are pointers to functions. The func given in this example for instance is

int
func (double t, const double y[], double f[],
void *params)
{
double mu = *(double *)params;
f[0] = y[1];
f[1] = -y[0] - mu*y[1]*(y[0]*y[0] - 1);
return GSL_SUCCESS;
}

What I want to do is provide a 'func' that is a pointer to a member function of an instantiated object. This is because the func needs to know a lot of information that is contained in that object. In this case a bunch of splines as well as some other functions. It is painful to have to make all of these have global scope just so this function can see them.

Can anyone suggest a solution? I would be most appreciative!
Phys.Org News Partner Science news on Phys.org
'Office life' of bacteria may be their weak spot
Lunar explorers will walk at higher speeds than thought
Philips introduces BlueTouch, PulseRelief control for pain relief
GuyIncognito
#2
May18-08, 11:20 PM
P: 1
I feel your pain, I wasted many hours trying to integrate GSL into my C++ code. There is no way that you can pass a pointer-to-member function to the GSL routines because they are of a different type than a pointer-to-function. For example, for the function:

double func(double, void*)

the type will vary depending on whether it is an ordinary function, a non-static member function of some class, or a static member function of a class.

- It is of type double (*)(double, void*) if it's an ordinary function or a static member function of a class.

- It is of type double (MyClass::*)(double, void*) if it's a non-static member function of class MyClass

The trick to working with C++ and GSL is to write a wrapper class that has a static member function of the type required by GSL, and that takes as an input your function class.

As an example, I wrote a quick and dirty solver class which used the root finding algorithms in GSL. To do so, I used the following function wrapper class which is initialised with a class containing the function I want to solve (this class is assumed to provide operator(double)) and the value I am trying to solve for.

template <typename T>
class FunctionWrapper : private boost::noncopyable {
public:
static void initialise(const boost::shared_ptr<T>& funcPtr, double target = 0) {
_funcPtr = funcPtr;
_target = target;
}

static double evaluate(double x, void* params) {

return _funcPtr->operator()(x) - _target;
}

protected:
FunctionWrapper() {}

private:
static boost::shared_ptr<T> _funcPtr;
static double _target;
};

template <typename T>
boost::shared_ptr<T> FunctionWrapper<T>::_funcPtr;

template <typename T>
double FunctionWrapper<T>::_target;


My wrapper class and GSL function are then initialised as follows:

gsl_function F;

FunctionWrapper<FunctionType>::initialise(funcPtr, target);
F.function = FunctionWrapper<FunctionType>::evaluate;
F.params = NULL;

I'm a little short on time at the moment, but hopefully the above makes some sense and the formatting isn't too messed up. Let me know if you have any further problems.
Wallace
#3
May18-08, 11:28 PM
Sci Advisor
P: 1,253
Thanks! I must admit I don't follow precisely a lot of the code you posted, I haven't got to using templates etc very much yet (still a C++ newb really) although I get the jist of what you are suggesting. I think I can work it out from your advice and the code, I'll let you know if I run into problems I can't solve.

Thanks again for your help!


Register to reply

Related Discussions
Doing a presentation. Need some pointers. Chemistry 1
Coding a Bubble Sort routine using a pointer array Programming & Computer Science 4
New and looking for pointers. General Discussion 0
Pointers freak me out! Programming & Computer Science 5
Need some pointers Introductory Physics Homework 21