2011-07-26 2 views
1

Я читаю книгу Даоки Янга «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::function и std::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; 
    } 
} 
Смежные вопросы