Function pointers working like closures in C ++

Is there a way in C ++ to effectively create a closure that will be a function pointer? I am using the Gnu Science Library and I need to create a gsl_function . This function should effectively "close" a couple of parameters available when creating it. Is there a good trick to create closures, so I don’t need to pass all of them as parameters in the gsl_function structure? If not, should I just pass a pointer to an array containing these parameters?

EDIT I tried using boost :: bind as follows:

#include <gsl/gsl_integration.h> #include <boost/bind.hpp> #include "bondpricecalculator.h" #include "functions.h" double integrand (double xi, double t, double x, void * p) { Functions *functions = (Functions *) p; double vx = functions->v(x); return functions->rho0(x)*exp(vx * xi - 0.5 * vx * vx * t); } double BondPriceCalculator::value(double t, double T, double xi) { gsl_integration_workspace * w = gsl_integration_workspace_alloc (10000); gsl_function F; F.function = &boost::bind(integrand, xi, t, _1, _2); F.params = &functions; double integral_t; double integral_T; double error; int res = gsl_integration_qags(&F, T, 1e+14, 0, 1e-7, 10000, w, &integral_T, &error); if(res) { throw "Error intgrating"; } int res = gsl_integration_qags(&F, T, 1e+14, 0, 1e-7, 10000, w, &integral_t, &error); if(res) { throw "Error intgrating"; } return integral_T/integral_t; } 

but I got the following error message:

 /home/ga/svn/PhD/inflation/cpp/ioi/bondpricecalculator.cpp:20: error: cannot convert 'boost::_bi::bind_t<double, double (*)(double, double, double, void*), boost::_bi::list4<boost::_bi::value<double>, boost::_bi::value<double>, boost::arg<1>, boost::arg<2> > >*' to 'double (*)(double, void*)' in assignment 
+4
source share
4 answers

I found the code below.

http://bytes.com/topic/c/answers/657124-interface-problem

 // Use in combination with boost::bind. template<class F> static double gslFunctionAdapter( double x, void* p) { // Here I do recover the "right" pointer, safer to use static_cast // than reinterpret_cast. F* function = static_cast<F*>( p ); return (*function)( x ); } template<class F> gsl_function convertToGslFunction( const F& f ) { gsl_function gslFunction; const void* p = &f; assert (p != 0); gslFunction.function = &gslFunctionAdapter<F>; // Just to eliminate the const. gslFunction.params = const_cast<void*>( p ); return gslFunction; } 

and use it like

 gslFunction gslF = convertToGslFunction( boost::bind( &Sde::drift, &sde, _1 ) ); 
+2
source

Take a look at this simple example of combining boost :: bind and boost :: functions.

+2
source

I guess from all these gsl_ prefixes that the library is not C ++, but simple C. This means that it does not clog C ++ closures (functors). You cannot pass the C ++ functor to C. You will need to skip the void pointers, cross your fingers and rethink them in the C oblivion.

+2
source

Although bradgonesurfing gave a good answer that would work for converting closures to gsl_function without any further thought, I would like to share with you an idiom for direct translation from C ++ to C.

Suppose you have a closure:

 double a; [&a](double x){return a+x;} 

You would convert this conversion to an equivalent function pointer icon as follows:

 struct paramsAPlusX{ double* a; paramsAPlusX(double & a_):a(&a_){} } double funcAPlusX(double x, void* params){ paramsAPlusX* p= (paramsAPlusX*)params; return *(p->a) + x; } //calling code: double a; paramsAPlusX params(a); gsl_function f; f.function=funcAPlusX; f.params=&paramsAPlusX; //use f here. 

Many C libraries use this idiom, and they do not all use a structure for it (they often pass it as two separate parameters to a function), so automatic conversion is not always possible.

+1
source

Source: https://habr.com/ru/post/1314942/


All Articles