Вы в ловушке (плохой) дизайн выбор GSL в использовании C (вместо C++), чтобы обеспечить указатель на функцию C-стиля. Таким образом, вы не можете использовать (C++ стиль) функции-объекты (функтор), но должны предоставлять указатель на реальную функцию, и нельзя генерировать функцию так же, как можно размножить функторы.
(Не рекомендуется) Вы можете использовать глобальную переменную для хранения фактической функции (a_squared
), а затем определить конкретный gsl_function
, что на самом деле вызывает эту глобальную переменную:
// from some gsl header:
extern "C" {
typedef double gsl_function(double, void*);
// calls func(arg,data_passed_to_func)
double gsl_api_function(gsl_function*func, void*data_passed_to_func);
}
// in your source code
double(*target_func)(double); // global variable can be hidden in some namespace
extern "C" {
double funtion_calling_target(double, void*)
}
double funtion_calling_target(double arg, void*)
{
return target_func(arg);
}
bool test(double x, double(*func)(double))
{
target_func = func;
return x < gsl_api_function(function_calling_target,0);
}
(пряча target_func
, как статический член какого-либо класса, так как в ответе Аткинса по-прежнему требуется глобальная переменная). Это работает, но плохо, так как 1) этот механизм требует глобальной переменной и 2) позволяет использовать только одну целевую функцию в любое время (что может быть трудно гарантировать).
(Рекомендован) Однако вы можете определить специальную функцию, которая принимает в качестве аргумента другой указатель функции и передает его как элемент данных. На самом деле идея дизайна gsl_function
: void*
может указывать на любые вспомогательные данные, которые могут потребоваться этой функции. Такие данные могут быть другой функцией.
// your header
extern "C" {
double function_of_double(double, void*);
}
inline double function_of_double(double arg, void*func)
{
typedef double(*func_of_double)(double);
return reinterpret_cast<func_of_double>(func)(arg);
}
// your application
bool test(double x, double(*func)(double))
{
return x < gsl_api_function(function_of_double, (void*)(func));
}
Это не требует глобальной переменной и работает с множеством различных одновременных функций, которые вы хотите. Конечно, здесь вы возитесь с void*
, тем, что каждый здравомыслящий программист на С ++ терпит неудачу, но тогда вы используете ужасную библиотеку C, основанную на манипуляциях void*
.
Почему это помечено 'C++'? GSL является библиотекой C и требует указателя функции типа C. Поэтому любое решение, основанное на функциональности C++ (например, 'std :: bind'), не выполняется. – Walter
Функциональность C++ не сбой, если вы используете небольшую обертку @Walter - и которая включает lambda и 'std :: bind'. См. Мой ответ –