gpt4 book ai didi

c++ - 在c++中使用gsl时如何避免静态成员函数

转载 作者:可可西里 更新时间:2023-11-01 17:41:56 26 4
gpt4 key购买 nike

我想在 C++ 类中使用 GSL 而无需将成员函数声明为 static。这样做的原因是因为我不太了解它们并且我不确定线程​​安全性。根据我的阅读,std::function 可能是一个解决方案,但我不确定如何使用它。

我的问题归结为如何删除 g 声明中的 static

#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";
}

更新(一):

我尝试将 gsl_monte_function G = { &g, 3, 0 }; 更改为 gsl_monte_function G = { bind(&A::g, this,_1,_2,_3), 3, 0 }; 但没有成功

更新 (2):我尝试使用 assigning std::function to a member function但它也没有用。

更新 (3)最后我写了一个非成员函数:

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;
};

它有效,但这是一个困惑的解决方案,因为我需要编写一个辅助函数。使用 lambda、函数和绑定(bind),应该有一种方法可以使类中的所有内容都合乎逻辑。

最佳答案

您可以使用以下代码轻松包装成员函数(这是一个众所周知的解决方案)

 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 中。示例:

gsl_function_pp Fp( std::bind(&Class::member_function, &(*this),  std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);

但是,在将成员函数包装在 gsl 集成例程中之前,您应该了解 std::function 的性能损失。参见 template vs std::function .为避免这种性能影响(这对您来说可能很重要,也可能不重要),您应该使用如下所示的模板

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);
}
};

在这种情况下,要调用成员函数,您需要以下内容

 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::function。

关于c++ - 在c++中使用gsl时如何避免静态成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13074756/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com