0

I am working on an optimization algorithm, in my algorithm, I need to use a function pointer to pass the function into the optimizer

the class definition:

class Downhill
{
public: //
    Downhill(std::string fpath);
    ~Downhill();
    void run();
private:
    /*objfun will be passed to amoeba function by function pointer*/
    float objfun1(float *p,int ndim);
    float objfun2(float *p,int ndim);
    float objfun3(float *p,int ndim);
    void amoeba(float **p, float pval[], int ndim, float(*funk)(float *, int ndim), float ftol, int &niter);
  
private:

    float ftol;
    float TINY = 1E-10;
    int NMAX = 5000;
    std::ofstream fout;
};

In the declaration of member function run(), I did as:

float(*funk)(float *p, int dim);
funk = &(this->objfun1); // I define the function pointer here
amoeba(p, pval, ndim, funk, ftol, niter);

And I had the compiler errer:

error C2276:  '&': illegal operation on bound member function expression

How can I refer a member function in another member function? Thank you very much!

YS_Jin
  • 55
  • 4
  • 1
    You cannot assign a member function to a function pointer. They are different things. Maybe you can use a pointer to a member function instead. Hard to say from the posted code. – john Jul 01 '22 at 21:07
  • It looks like `TINY` and `NMAX` should be static const. – Goswin von Brederlow Jul 01 '22 at 21:10
  • It might optimize better if you pass `funk` as template argument but that is something you have to benchmark. Also it would be better to pass `std::span`, `std::array` or `std::vector` instead of pointer + size. References instead of pointers are alsomore C++-ish. amoeba seems to take `p` as out parameter, if so it would be better to return it. – Goswin von Brederlow Jul 01 '22 at 21:14
  • _" I need to use a function pointer to pass the function into the optimizer"_ - Really? Is that the only interface possible? – Ted Lyngmo Jul 01 '22 at 21:15
  • If I am not mistaken the C++ compiler tries to optimize non-subclass of virtual class classes out of existence at compiletime so that all the operations are inlined and the class becomes a pure data object, and there are no functions to point to. If it was a subclass(of an "interface") you could do the unthinkable and hack your way into the vtable of the class and rip the function pointer out of there, at the cost of portability and respect of fellow C++ programmers. – Dmytro Jul 01 '22 at 21:19
  • Small correction, under -O0 and default, g++ leaves the functions in and actually calls them, but under -Os, -O1, -O2, -O3 there are no traces of the class ever being there in the resulting binary. – Dmytro Jul 01 '22 at 21:39
  • Does this answer your question? [Function pointer to member function](https://stackoverflow.com/questions/2402579/function-pointer-to-member-function) – JaMiT Jul 01 '22 at 22:00
  • @Dmitry *"If I am not mistaken the C++ compiler tries to optimize [...]"* -- it is true that optimizing compilers try to optimize, but those optimizations must not change functionality. So, yes, the compiler will try to optimize every function out of existence (not just member functions). However, using the address of a function will prevent it from being optimized out of existence, because its address is needed. (This is why virtual functions do not get optimized out of existence -- their addresses are used to build virtual function tables.) – JaMiT Jul 01 '22 at 22:06

1 Answers1

5

When taking the address of a method pointer, you need to include the name of the class. So in this case, the appropriate syntax would be:

&Downhill::objfun1

At the same time, a non-static method pointer is not interchangeable with a regular function pointer. So you would need to declare the third argument of amoeba as:

float(Downhill::*funk)(float *, int ndim)

And then you would need to call the function as this->*funk(...). If you need to bundle the identity of the object with a pointer, then you might consider making the third argument a std::function<float(float*, int)> (and then using a lambda or std::bind). However in your case that might not be necessary.

user3188445
  • 4,062
  • 16
  • 26