Hi, I have some objects of a class that inherits from ROOT::Math::Interpolator with an ::Eval method that has the right signature to make TF1 objects: Double_t MyInterpolator::Eval(Double_t *, Double_t *). In CINT, I can do this:
MyInterpolator * myp = make_interpolator();
TF1 f1("f1",myp,&MyInterpolator::Eval,xmin,xmax,0,"MyInterpolator","Eval");
and it works fine. I wanted to automate some of this and wrote a function:
TF1 makeTF1(MyInterpolator * myp,Double_t xmin = -0.7,Double_t xmax = -0.7)
{
TF1 f1("f1",myp,&MyInterpolator,xmin,xmax,0,"MyInterpolator","Eval");
return f1;
}
but I get a errors about no available constructor:
/Users/jfcaron/Projects/Proto2BeamTest2/./t2x.C:188:7: error: no matching constructor for initialization of 'TF1'
TF1 f1("f1",myp,&MyInterpolator::Eval,lims.first,lims.second,0,"MyInterpolator","Eval");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/local/include/root/TF1.h:190:4: note: candidate constructor not viable: no overload of 'Eval' matching 'void *' for 3rd argument
TF1(const char *name, void *ptr, void *,Double_t xmin, Double_t xmax, Int_t npar, const char *className, const char *methodName = 0);
^
/opt/local/include/root/TF1.h:156:4: note: candidate template ignored: couldn't infer template argument 'MemFn'
TF1(const char *name, const PtrObj& p, MemFn memFn, Double_t xmin, Double_t xmax, Int_t npar, const char * = 0, const char * = 0) :
(and more lines with constructors having the wrong number of arguments). I tried many variations like doing a (void*) cast, but nothing worked until I looked up member function pointers. Following some instructions from a blog, I ended up making this:
typedef Double_t (MyInterpolator::*FNMETHOD) (Double_t *, Double_t *) const;
TF1 makeTF1(MyInterpolator * myp,Double_t xmin = -0.7,Double_t xmax = -0.7)
{
FNMETHOD m = &MyInterpolator::Eval;
TF1 f1("f1",myp,m,xmin,xmax,0,"MyInterpolator","Eval");
return f1;
}
I am happy that it works, but I am less happy that it took a long time to get this working. What is the essential difference? It looks like I am just giving the member pointer a temporary name “m” instead of naming it directly in the constructor, why does the TF1 care? How does CINT figure out to do the right thing?
Jean-François