Problem TMinuit

I’ve been trying to use TMinuit to fit a function. I believe the error is in my implementation of TMinuit::SetFCN. I have the following error : " error: invalid use of non-static member function " in SetFCN(MyFunction). How can I solve this problem??

void MyClass::MyFunction(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t errflag)
{

//Function does stuff

}

void MyClass::OtherFunction(Int_t int1, Int_t int2)
{

//Function does stuff
TMinuit *minuit = new TMinuit(5);
minuit -> SetFCN(MyFunction);
}

ROOT Version:_ 6.10/04
Compiler:_ gcc


Hello @anna_rotolo,

You are getting this error because TMinuit::SetFCN() takes a pointer to a non-member function (note that, in C++, member functions are invoked on an object, and hence internally receive a pointer to this).
To fix this, you must either:

  1. Declare MyClass::MyFunction() as static in the definition of MyClass, i.e.
static void MyFunction(Int_t &, Double_t *, Double_t &, Double_t *, Int_t);
  1. Use a lambda expression instead, i.e.
void MyClass::OtherFunction(Int_t int1, Int_t int2) {
    auto fcn = [] (Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t errflag) {
        // The body of your former MyClass::MyFunction should be moved here.
    };

    //Function does stuff
    TMinuit *minuit = new TMinuit(5);
    minuit->SetFCN(fcn);
}

Cheers,
J.

Hi @jalopezg ! Thanks for your reply. The first solution can’t be applied because some quantities of MyFunction are used in other parts of my code, so can you explain the second one again? Sorry, I didn’t understand how to implement the second option you suggested me.

Hi @anna_rotolo,

I don’t see what you mean here. My guess is that maybe MyFunction is using the value of some data members of the class?

Here I was suggesting to moving the logic of MyFuncion onto a C++ lambda. Basically, lambda expressions behave as callable functions -that may additionally capture parts of the lexical context where it is declared-.

Non-technically speaking, they can be used to define a function inline in the place where it is used. See my example below.

void MyClass::OtherFunction(Int_t int1, Int_t int2) {
    auto fcn = [this] (Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t errflag) {
        // Whatever code that you had in MyClass::MyFunction before, should be moved here.
        //
        // I have captured `this` (see above) so you can access members of this instance normally, e.g.
        // if (this->foo) { /* ... */ }
    };

    // ...
    TMinuit *minuit = new TMinuit(5);
    minuit->SetFCN(fcn);
}

I hope to have clarified this a bit more. You can start by modifying the example above to fit your requirements.

Cheers,
J.

Hi @jalopezg, I 've used the second method you suggest me and I I send you the error message that came out : " error: no matching function for call to ‘TMinuit::SetFCN(Reconstruction::OtherFunction(ALLTRACK_STRUCT*, int, double*)::<lambda(double*, double*)>&)’
minuit->SetFCN(MyFunction);
^
In file included from Reconstruction.h:14:0,
from Reconstruction.cpp:1:
/mnt/c/Users/ela/Desktop/ROOT/root/include/TMinuit.h:262:19: note: candidate: virtual void TMinuit::SetFCN(void ()(Int_t&, Double_t, Double_t&, Double_t*, Int_t))
virtual void SetFCN(void (*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t)); ".
I don’t know how to solve it…

For the first method, as you said, MyFunction is using the value of some data members of the class. If I declare these data/variables in OtherFuction and not in my Private part of the class, can I solve the problem in this way?

Hi @anna_rotolo,

Basically, the compiler is telling you that SetFCN() expects to be passed a function that takes exactly 5 arguments of the types Int_t &, Double_t *, Double_t &f, Double_t *, Int_t.

Actually, it would be useful to take a look at the relevant code. Could you attach a minimal reproducer of the problem?

Cheers,
J.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.