2014-10-29 2 views
2

Я работаю с gsl для интеграции функции. Эта функция встроена в лямбда-функцию, которая имеет в качестве входной сигнал double и void *, а в качестве вывода - double. Теперь все работает нормально, если я использую лямбду без какого-либо захвата переменной. Но если я выполняю переменную захвата, она больше не работает.Численное интегрирование лямбда-функции с gsl

Может ли кто-нибудь объяснить мне, почему так?

Вот два фрагмента кода, который я сделал, чтобы объяснить мою проблему:

Это один работает отлично:

int main(int argc, char **argv) 
{ 

    double beg = 0; 
    double end = 10; 

    auto f = [] (double x, void * p) {return 2.0;}; 

    gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE); 

    double result; 
    double error; 

    gsl_function F; 
    F.function = f; 
    F.params = NULL; 

    gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error); 

    cout<<result<<endl; 

} 

В то время как это один

int main(int argc, char **argv) 
{ 

    double beg = 0; 
    double end = 10; 

    double p = 2.0; 

    auto f = [&] (double x, void * p) {return p;}; 

    gsl_integration_workspace * w = gsl_integration_workspace_alloc (GSL_INTEGRATION_WORKSPACE_SIZE); 

    double result; 
    double error; 

    gsl_function F; 
    F.function = f; 
    F.params = NULL; 

    gsl_integration_qags (&F, beg, end, 0, GSL_INTEGRATION_RELATIVE_PRECISION, GSL_INTEGRATION_WORKSPACE_SIZE, w, &result, &error); 

    cout<<result<<endl; 

} 

Урожайность на линии

F.function = f; 

следующее сообщение об ошибке:

Assigning to 'double (*)(double, void *)' from incompatible type '<lambda at /[omissis]/main.cpp>' 

ответ

3

Ответ, заданный пользователем @ user657267, верен. Вот почему нужна небольшая обертка для преобразования lambas с захватом в gsl_function.

Here is the wrapper for the f gsl_function и Here is the wrapper for the fdf gsl_function

Вы можете преобразовать лямбда-функцию gsl_function после использования обертки, предложенной в этих двух ответах следующим образом (я не придумал версию с стандом :: функцией, она была хорошо известна Ответ. Версия шаблона, которую я не видел до моего ответа).

// std::function version 
double a = 1; 
gsl_function_pp Fp([=](double x)->double{return a*x;}); 
gsl_function *F = static_cast<gsl_function*>(&Fp); 

//template version 
double a = 1; 
auto ptr = [=](double x)->double{return a*x;}; 
gsl_function_pp<decltype(ptr)> Fp(ptr); 
gsl_function *F = static_cast<gsl_function*>(&Fp); 
+0

Это именно то, что я искал! –

+0

Если вам понравилось, вы можете дать голосование другим ответам :) –

+0

где находится 'std :: function'? – Walter

2

только лямбда без захватов может быть преобразована в указателях на функцию.

[expr.prim.lambda]

6 The closure type for a non-generic lambda-expression with no lambda-capture has a public non-virtual non explicit const conversion function to pointer to function with C++ language linkage (7.5) having the same parameter and return types as the closure type’s function call operator.

По сути, это означает, что

[] (double, void*) {return 2.0;}; 

действует, как если бы оно было определено как

class Lambda 
{ 
public: 
    double operator()(double, void*); 
    operator double(*)(double, void*)() const; 
}; 

, если лямбда имеет однако функция преобразования не определена, и лямбда не может быть преобразована в регулярную функцию poin тер.