Вопрос об использовании функции-члена класса в качестве параметра шаблона - PullRequest
1 голос
/ 26 июля 2011

Я читаю книгу Даоци Янга "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
}

Ответы [ 2 ]

1 голос
/ 20 ноября 2011

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;
    }
}
1 голос
/ 26 июля 2011

Аргументы шаблона должны быть константными выражениями или типами времени компиляции, а функции-члены в любом случае требуют специальной обработки. Вместо этого используйте 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 вместо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...