开发者

Question on using class member function as template parameter

I'm reading the book by Daoqi Yang "C++ and Object Oriented Numeric Computing for Scientists and Engineers". He has a similar example to what I am showing below, but the exceptions are the class "P" I define and the second to last line (which doesn't work). My question is: why does my compiler generate and error when I supply the function member f.integrand? What can I do to correct this? The errors being generated are C3867, C2440, and C2973.

Here is the code:

class P{
public:
double integrand(double x){
    return (exp(-x*x));
}
};

template<double F(double)>
double trapezoidal(double a, double b, int n)
{
    double h=(b-a)/n;
    double sum=F(a)*0.5;
    for(int i=1;i<n;i++)
    {
        sum+=F(a+i*h);
    }
    sum+=F(b)*0.5;

    return (sum*h);
}

double integrand2(double x){
    return (exp(-x*x));
}

int main(){
    P开发者_如何学C f;
    cout<< trapezoidal<integrand2>(0,1,100)<<endl;    // this works
    cout<< trapezoidal<f.integrand>(0,1,100)<<endl;   // this doesn't work
}


Template arguments must be compile-time constant expressions or types, and member functions require special handling anyway. Instead of doing this, use boost::function<> as an argument, and boost::bind to create the functor, e.g.

double trapezoidal(double, double, boost::function<double(double)>);

// ...

P f;
trapezoidal(0, 1, 100, integrand2);
trapezoidal(0, 1, 100, boost::bind(&P::integrand, boost::ref(f)));

If you have 0x-capable compiler, you can use std::function and std::bind instead.


Cat Plus Plus is correct - boost::bind is a good way to do this easily. I've also included an alternate solution with the following snippet of code:

class P{
private:
    double a;
public:
    double integrand(double x){
        return (a*exp(-x*x));
    }
    void setA(double y){
        a = y;
    }
    void getA(){
        cout<<a<<endl;
    }

    struct integrand_caller {
        P* p;
        integrand_caller(P& aP) : p(&aP) {};
        double operator()(double x) const {
            return p->integrand(x);
        };
    };
};

template <typename Evaluator, typename VectorType>
VectorType trapezoidal(Evaluator f, const VectorType& a, const VectorType& b, int n)
{
    VectorType h=(b-a)/n;
    VectorType sum=f(a)*0.5;
    for(int i=1;i<n;i++)
    {
        sum+=f(a+i*h);
    }
    sum += f(b)*0.5;

    return (sum*h);
}

double integrand2(double x){
    return (exp(-x*x));
}

int main(){
    P f[5];
    for(int i=0;i<5;i++){
        f[i].setA(5*i);
        f[i].getA();
        cout<< trapezoidal(P::integrand_caller(f[i]),(double)0, (double)1, 100) << endl;
        cout<<trapezoidal(boost::bind(&P::integrand,f[i],_1), 0.0, 1.0, 100)<<"\n"<<endl;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜