将GSL与C 一起使用时,如何避免静态成员函数
how to avoid static member function when using gsl with c++
我想在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";
}
更新(1):
我尝试将gsl_monte_function G = { &g, 3, 0 };
更改为gsl_monte_function G = { bind(&A::g, this,_1,_2,_3), 3, 0 };
,但它不起作用
update(2):我尝试使用将std ::函数分配到成员函数,但也不起作用。
更新(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;
};
它起作用,但这是一个凌乱的解决方案,因为我需要编写一个辅助功能。使用lambdas,功能和绑定,应该有一种方法可以使所有逻辑中的所有内容都在类中。
您可以使用以下代码轻松包装成员功能(这是一个众所周知的解决方案)
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 ::绑定将成员函数包裹在std ::函数中。示例:
gsl_function_pp Fp( std::bind(&Class::member_function, &(*this), std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);
但是,在包装GSL集成例程中包装成员功能之前,您应该了解STD ::功能的性能惩罚。请参阅模板与STD ::功能。为了避免这种性能命中(这可能对您至关重要),应使用模板如下所示
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:链接模板vs std ::函数解释说,编译器通常比std ::函数更容易优化模板(如果您的代码执行重型数值计算,这对于性能至关重要)。因此,在第二个示例中,即使很艰难的解决方法似乎更麻烦,我更喜欢模板,而不是std :: function。
gsl采用C型功能“int (*)(char,float)”
而不是C - 类型“int (Fred::*)(char,float)”
。要将成员函数转换为C型函数,您需要添加static
。
请参阅"指针到会员功能"的类型与"指针到功能"不同?
为什么在这种情况下您担心静态功能?除非存在静态函数,否则在静态函数中声明的变量和/或对象,除非它们本身是静态的(在您的情况下它们不是静态)。
。您的代码无法做某事?
对不起,但是您要做的事情没有任何意义。无论您担心什么线程安全问题,都不会通过添加或删除static
关键字来解决它们。
如果g
的操作需要以某种方式进行A
实例,则您将进行g
非静态的唯一原因。G当前的实现不需要这样的实例。
注意,您还可以使g
成为全局函数,而无需static
关键字。您的情况没有明显的区别。但是,在您的情况下,将使用g
作为静态功能是更好的样式。
另外,这里是有关指针(静态/非静态)成员功能的一些相关材料。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如何在C++中使用非静态成员函数作为回调函数
- (C++)为什么静态成员可以在初始化之前使用
- 类的全局对象和静态成员
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- 模板化类中静态成员的延迟初始化
- 使用静态成员声明类时遇到问题
- C++:是否可以使用非静态成员变量模板?
- 静态成员函数使用相同的名称时出现模板类型名称错误
- 如何在复杂继承中访问静态成员变量
- 在 nullptr 上调用无状态类的非静态成员函数是否合法?
- 如何在友元函数中使用静态成员而不添加前缀 [类名]::
- C++构造函数和静态成员
- 使用没有对象的另一个类的成员函数,避免静态
- 应在共享库中避免静态成员功能
- 将GSL与C 一起使用时,如何避免静态成员函数
- 当使用来自c的回调接口时,避免在c++中使用静态成员函数
- 避免在初始化静态成员时使用new()
- 如何以线程安全的方式避免静态数据成员初始化失败
- 'constexpr'非静态成员函数不会隐式'const'在 C++1y 中;添加'const'以避免行为更改