cadenzah
cadenzah

Reputation: 978

Calling function that has template function pointer argument

I'm not used to C++ templates, and I have a problem using the libraries made with templates.

These are math-related libraries included in Numerical Methods in C 3rd edition, and I got a problem with using the methods.

Below is the function that I'm trying to use:

// roots.h
//...
template <class T>
// Doub is a defined type that is equal to double
Doub rtbis(T &func, const Doub x1, const Doub x2, const Doub xacc) {
    const Int JMAX=50;
    Doub dx,xmid,rtb;
    Doub f=func(x1);
    Doub fmid=func(x2);
    if (f*fmid >= 0.0) throw("Root must be bracketed for bisection in rtbis");
    rtb = f < 0.0 ? (dx=x2-x1,x1) : (dx=x1-x2,x2);
    for (Int j=0;j<JMAX;j++) {
        fmid=func(xmid=rtb+(dx *= 0.5));
        if (fmid <= 0.0) rtb=xmid;
        if (abs(dx) < xacc || fmid == 0.0) return rtb;
    }
    throw("Too many bisections in rtbis");
}
//...

And with this, in main.cpp I tried to call

// main.cpp
#include "nr3.h"
#include "roots.h"
#include "bessel.h"

int main() {
    Doub (Bessjy::*fptr) (Doub) = &Bessjy::j0;
    Doub root = 0;

    root = rtbis<double (Bessjy::*)(double)>(fptr,1.0,10.0,0.000001);

    std::cout << root << std::endl;
}

I used g++ to compile, and the error message saids:

error: called object type 'double (Bessjy::*)(double)' is not a function or function pointer
Doub f=func(x1);
note: in instantiation of function template specialization
'rtbis&lt;double (Bessjy::*)(double)&gt;' requested here
root = rtbis&lt;double (Bessjy::*)(double)'&gt;(fptr,1.0,10.0,0.000001);

I modified the code as the compiler told me to do, but still it repeats the same error message.

I don't get how to solve it. Certainly I'm missing the important syntax matter.

Upvotes: 1

Views: 429

Answers (1)

crayzeewulf
crayzeewulf

Reputation: 6010

(Posting this for completion, based on discussion in comments, for others to find if they have similar questions).

Since Bessjy::j0() is a static member function, as mentioned in comments below the question, its type is the same as if it were an ordinary function. You can pass it as an argument to rtbis<>() just like any other ordinary function. Here is an example:

#include <iostream>

using Int = int ;
using Doub = double ;

class Bessjy
{
public:
    static Doub j0(Doub x1) { return x1*x1 + 60.0 ; }     
} ;

template <class T>
Doub rtbis(const T& func, const Doub x1, const Doub x2, const Doub xacc) { 
    return func(x1) ;
}

int main() 
{
    const auto root = rtbis(Bessjy::j0,1.0,10.0,0.000001);
    std::cout << root << std::endl;
    return 0 ;
}

Try it online here. Read this for additional information and caveats.

Upvotes: 2

Related Questions