如何在使用gsl和c ++时避免静态成员函数 [英] how to avoid static member function when using gsl with c++
问题描述
我想在c ++类中使用GSL,而不声明成员函数 static
。这样做的原因是因为我不太了解他们,我不知道线程安全。从我读到的, std :: function
可能是一个解决方案,但我不知道如何使用它。
I would like to use GSL within a c++ class without declaring member functions as static
. The reason for this is because I don't know them too well and I'm not sure about thread safety. From what I read, std::function
might be a solution but I'm not sure how to use it.
我的问题是如何删除 g
?
#include<iostream>
#include <functional>
#include <stdlib.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_monte.h>
#include <gsl/gsl_monte_plain.h>
#include <gsl/gsl_monte_miser.h>
#include <gsl/gsl_monte_vegas.h>
using namespace std;
class A {
public:
static double g (double *k, size_t dim, void *params)
{
double A = 1.0 / (M_PI * M_PI * M_PI);
return A / (1.0 - cos (k[0]) * cos (k[1]) * cos (k[2]));
}
double result() {
double res, err;
double xl[3] = { 0, 0, 0 };
double xu[3] = { M_PI, M_PI, M_PI };
const gsl_rng_type *T;
gsl_rng *r;
////// the following 3 lines didn't work ///////
//function<double(A,double*, size_t, void*)> fg;
//fg = &A::g;
//gsl_monte_function G = { &fg, 3, 0 };
gsl_monte_function G = { &g, 3, 0 };
size_t calls = 500000;
gsl_rng_env_setup ();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
{
gsl_monte_plain_state *s = gsl_monte_plain_alloc (3);
gsl_monte_plain_integrate (&G, xl, xu, 3, calls, r, s, &res, &err);
gsl_monte_plain_free (s);
}
gsl_rng_free (r);
return res;
}
};
main() {
A a;
cout <<"gsl mc result is " << a.result() <<"\n";
}
更新(1):
我尝试更改 gsl_monte_function G = {& g,3,0}; 到
gsl_monte_function G = {bind(& A :: g,this,_1,_2,_3),3,0};
但不起作用
I tried changing gsl_monte_function G = { &g, 3, 0 };
to gsl_monte_function G = { bind(&A::g, this,_1,_2,_3), 3, 0 };
but it didn't work
Update (2): I tried using assigning std::function to a member function but it didn't work either.
更新(3)
到最后我写了一个非成员函数:
Update (3) in the end I wrote a non-member function:
double gmf (double *k, size_t dim, void *params) {
auto *mf = static_cast<A*>(params);
return abs(mf->g(k,dim,params));
//return 1.0;
};
它工作,但它是一个凌乱的解决方案,因为我需要写一个帮助函数。使用lambdas,function和bind,应该有一种方法可以让一切都在逻辑上。
It worked but it's a messy solution because I needed to write a helper function. With lambdas,function and bind, there should be a way to have everything logical within the class.
推荐答案
函数使用以下代码(这是一个公知的解决方案)
You can easily wrap member functions using the following code (which is a well known solution)
class gsl_function_pp : public gsl_function
{
public:
gsl_function_pp(std::function<double(double)> const& func) : _func(func){
function=&gsl_function_pp::invoke;
params=this;
}
private:
std::function<double(double)> _func;
static double invoke(double x, void *params) {
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};
然后你可以使用std :: bind在std :: function中封装成员函数。示例:
Then you can use std::bind to wrap the member function in a std::function. Example:
gsl_function_pp Fp( std::bind(&Class::member_function, &(*this), std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);
<集成例程。请参见 template vs std :: function 。为了避免这种性能损失(这可能对您或可能不是至关重要的),您应该使用如下所示的模板
However, you should be aware about the performance penalties of std::function before wrapping member functions inside gsl integration routine. See template vs std::function . To avoid this performance hit (which may or may not be critical for you), you should use templates as shown below
template< typename F >
class gsl_function_pp : public gsl_function {
public:
gsl_function_pp(const F& func) : _func(func) {
function = &gsl_function_pp::invoke;
params=this;
}
private:
const F& _func;
static double invoke(double x, void *params) {
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};
在这种情况下,要调用成员函数,您需要以下
In this case, to call a member function you need the following
Class* ptr2 = this;
auto ptr = [=](double x)->double{return ptr2->foo(x);};
gsl_function_pp<decltype(ptr)> Fp(ptr);
gsl_function *F = static_cast<gsl_function*>(&Fp);
PS:链接 template vs std :: function 解释了编译器通常比std :: function更容易优化模板(这对于性能至关重要,如果你的代码进行大量的数值计算)。所以即使艰难的解决方法在第二个例子似乎更繁琐,我喜欢模板比std ::函数。
PS: the link template vs std::function explains that compiler usually has an easier time optimizing templates than std::function (which is critical for performance if your code is doing heavy numerical calculation). So even tough the workaround in the second example seems more cumbersome, I would prefer templates than std::function.
这篇关于如何在使用gsl和c ++时避免静态成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!