2011-07-26 184 views
1

我正在讀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 
} 

回答

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::functionstd::bind代替。

+0

很好的答案。我很樂意投它,但我沒有'名聲'來做。這絕對啓發我尋求替代解決方案。看到我發佈的答案... – Pasta23

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; 
    } 
} 
相關問題