1

first of all I know that this is not possible in C++. But I hope someone can tell be a workaround for my problem. I have a class which represents a mathematical function:

class myClass:
{
private:
public:
    myClass() {};
    double value(double, double){ /* doing some complicated calculation here */} };
    double integrate { /*calc*/ return integral; };
}

In integrate() I want to create a struct with a reference to value(). The struct is defined as follows:

struct gsl_monte_function_struct {
    double (*f)(double * x_array, size_t dim, void * params);
    size_t dim;
    void * params;
};

(I need this struct to call the Monte-Carlo integration routines from GSL)

As said before I know that this is forbidden in C++. But is there any possibility to use gsl_monte_function_struct with a member function of myClass? If it is not possible that myClass can integrate itself, is it possible to call gsl_monte_function_struct from outside the class with value() as reference? Thanks in advance!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
hansgans
  • 307
  • 4
  • 12

2 Answers2

2

If understand you corretly, you want a pointer to a member function of myClass. You can achieve this by declaring the member function pointer as:

double (myClass::*value)(double,double) 

This function can later be called on an instance as:

(instance.*value)(x,y);

Alternatively you can use std::bind to create a function object which can be called as an ordinary function without having to keep track of the instance on which it is called after the call to std::bind:

auto& value = std::bind(myClass::value, instance);
// ....
value(x,y);
Agentlien
  • 4,996
  • 1
  • 16
  • 27
  • It should be noted that invoking that member function pointer will require a pointer-to-member syntax, `->*` for example. There are examples of this on SO in several questions and answers. – WhozCraig Oct 30 '13 at 10:45
  • @WhozCraig That's a good point. Which is why I included the mention of std::bind to be able to avoid it. – Agentlien Oct 30 '13 at 10:50
  • Thanks for your answer: I tried: `auto d = std::bind(&myClass::value,instance,std::placeholders::_1);`. This works! But now I want to do: `double (*f)(double y) = d;` (this is the member function of gsl_monte_function). This fails! Any ideas? – hansgans Oct 30 '13 at 13:24
  • The error is `stdbind_example.cpp:29:13: error: no viable conversion from 'std::__1::__bind &>' to 'double (*)(double)' double (*f)(double y) =d;` – hansgans Oct 30 '13 at 13:26
  • @user2935834 The type of `d` is not actually a function pointer. It's a function object. You need to either make the gsl_monte_function_struct a template which depends on this type or use a member function pointer (double (myClass::*value)(double,double) and add a pointer to the instance (type myClass*) to your struct. – Agentlien Oct 30 '13 at 13:29
  • If i understand you correctly, what i want to do is impossible without changing `gsl_monte_function_struct`? – hansgans Oct 30 '13 at 13:31
  • @hansgans That is correct. The reason is that your function is a member of a class, and it is not static. This means the function needs to know on which object it is being called. If you need to solve this without changing `gsl_monte_function_struct` you need to either make your function static or move it outside of the class. So, consider this: why is it a non-static member function? – Agentlien Oct 30 '13 at 13:34
0

Ok so far I found two solutions:

1) (General solution) Using an abstract base class which has a static pointer to the current instance and a static function that calls a function of the derived class. The static function can be used with a function pointer.

Example:

struct gsl_monte{
   double (*f)(double y);
};

class myBase {
private:
  static myBase* instance;

public:
  myBase(){};
  static void setInstance(myBase* newOne);
  virtual double value(double x) =0;
  static double callValue(double x);//{return value(x);}
};

class myClass : public myBase {
   public:
      myClass(){};
      double value(double x) {  return x;  };
};

myBase* myBase::instance = new myClass();
double  myBase::callValue(double x){return instance->value(x);}
void myBase::setInstance(myBase* newOne){instance=newOne;};

double g(double xx) {return xx;};

int main(int argc, char** argv ){
   double x[2]; x[0]=1.3; x[1]=1.3;
   myClass* instance = new myClass();
   myBase::setInstance(instance);
   instance->value(3);
   std::cout << "Test " << myBase::callValue(5) << std::endl;
   gsl_monte T;
   T.f=&myBase::callValue;
   double (*f)(double y, void*) = &myBase::callValue;
}

2) (Solution specific to my problem) Fortunatly the desired function accepts a parameter pointer, which I can use to pass the current object:

#include <iostream>
#include <functional>
using namespace std::placeholders;

struct gsl_monte{
   double (*f)(double y, void*);
};

class myClass {
   public:
      myClass(){};
      double value(double x) {  return x;  };
};

double valueTT(double x, void* param) {  return static_cast<myClass*>(param)->value(x);  };

int main(int argc, char** argv ){
   double x[2]; x[0]=1.3; x[1]=1.3;
   myClass* instance = new myClass();
   instance->value(3);
   gsl_monte T;
   T.f=&valueTT;
   double (*f)(double y, void*) = &valueTT;
}
hansgans
  • 307
  • 4
  • 12