我正在阅读Daoqi Yang的书“C ++和面向对象的科学家和工程师的数字计算”。他有一个类似于我在下面显示的例子,但例外是我定义的类“P”和倒数第二行(它不起作用)。我的问题是:当我提供函数成员f.integrand时,为什么我的编译器生成并出错?我该怎么做才能纠正这个问题?生成的错误是C3867,C2440和C2973。
以下是代码:
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
}
答案 0 :(得分:1)
模板参数必须是编译时常量表达式或类型,而成员函数无论如何都需要特殊处理。不要这样做,而是使用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)));
如果你有支持0x的编译器,你可以改用std::function
和std::bind
。
答案 1 :(得分:1)
Cat Plus Plus是正确的 - boost::bind
是一种很容易做到这一点的好方法。我还提供了一个备用解决方案,其中包含以下代码片段:
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;
}
}