简体   繁体   English

关于使用class成员function作为模板参数的问题

[英]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".我正在读杨道奇的书《C++ 和 Object 面向科学家和工程师的面向数值计算》。 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).他有一个与我在下面展示的类似的示例,但例外情况是我定义的 class“P”和倒数第二行(不起作用)。 My question is: why does my compiler generate and error when I supply the function member f.integrand?我的问题是:当我提供 function 成员 f.integrand 时,为什么我的编译器会生成错误? What can I do to correct this?我该怎么做才能纠正这个问题? The errors being generated are C3867, C2440, and C2973.生成的错误是 C3867、C2440 和 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 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.模板 arguments 必须是编译时常量表达式或类型,成员函数无论如何都需要特殊处理。 Instead of doing this, use boost::function<> as an argument, and boost::bind to create the functor, eg不要这样做,而是使用boost::function<>作为参数,并使用boost::bind来创建仿函数,例如

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.如果您有支持 0x 的编译器,则可以改用std::functionstd::bind

Cat Plus Plus is correct - boost::bind is a good way to do this easily. Cat Plus Plus 是正确的 - boost::bind是轻松完成此操作的好方法。 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM