C++ 将成员函数指针传递给无类函数

C++ 将成员函数指针传递给无类函数,c++,argument-passing,member-function-pointers,C++,Argument Passing,Member Function Pointers,在下面的代码中,我无法找到将成员函数传递给通用根查找器的方法 #include <stdio.h> double OneDimBisector(double (*fun)(float), float a, float b, float tol){ double val;

在下面的代码中,我无法找到将成员函数传递给通用根查找器的方法

#include <stdio.h>

double OneDimBisector(double (*fun)(float), float a, float b, float tol){
 double val;                                                                                                                                                                           
 val = (*fun)(0.5*(b-a));    // actually: do proper bisection                                                                                                                          
 return val;                                                                                                                                                                           
}                                                                                                                                                                                      

class EOS {                                                                                                                                                                            
 public:                                                                                                                                                                               
  double S_array[10][10];    // actually: filled by constructor                                                                                                                        
  double S(double T, double P);                                                                                                                                                        

  double T_PS(double P, double S);                                                                                                                                                     
  double functForT_PS(double T);                                                                                                                                                       
  double (EOS::*pfunctForT_PS)(double);                                                                                                                                                
  double Sseek, Pseek;                                                                                                                                                                 
};                                                                                                                                                                                     


double EOS::S(double T, double P){                                                                                                                                                     
  double val = T+P;          // actually: interpolate in S_array                                                                                                                       
  return val;                                                                                                                                                                          
}                                                                                                                                                                                      

double EOS::functForT_PS(double T){                                                                                                                                                    
 return S(T,Pseek)-Sseek;                                                                                                                                                              
}                                                                                                                                                                                      

// Find T from P and S (T is invertible), assuming the intervals are ok
double EOS::T_PS(double P, double S0){
  double Tmin = 2., Tmax = 7., T1, tol=1e-8;
  pfunctForT_PS = &EOS::functForT_PS;
  Sseek = S0;
  Pseek = P;

  printf("\n %f\n", (*this.*pfunctForT_PS)(4.));         // no problem
  T1 = OneDimBisector(pfunctForT_PS, Tmin, Tmax, tol);   // wrong type for pfunctForT_PS

  return T1;
}

int main() {
  double P=3., S=8;
  EOS myEOS;

  printf("\n %f %f %f\n",P,S,myEOS.T_PS(P,S));
}
#包括
双一二等分线(双(*fun)(浮动)、浮动a、浮动b、浮动tol){
双val;
val=(*fun)(0.5*(b-a));//实际上:做适当的二等分
返回val;
}                                                                                                                                                                                      
类EOS{
公众:
双S_数组[10][10];//实际上:由构造函数填充
双S(双T,双P);
双T_P(双P,双S);
双功能端口(双T);
双人(EOS::*pfunctForT_PS)(双人);
双赛克,赛克;
};                                                                                                                                                                                     
双EOS::S(双T,双P){
double val=T+P;//实际上:在S_数组中插值
返回val;
}                                                                                                                                                                                      
双EOS::functForT_PS(双T){
返回S(T,Pseek)-Sseek;
}                                                                                                                                                                                      
//从P和S中求出T(T是可逆的),假设间隔是确定的
双EOS::T_PS(双P,双S0){
双Tmin=2,Tmax=7,T1,tol=1e-8;
pfunctForT_PS=&EOS::functForT_PS;
Sseek=S0;
Pseek=P;
printf(“\n%f\n”,(*this.*pfunctForT_PS)(4.);//没问题
T1=一个二等分线(pfunctForT_PS,Tmin,Tmax,tol);//pfunctForT_PS的类型错误
返回T1;
}
int main(){
双P=3,S=8;
EOS-myEOS;
printf(“\n%f%f%f\n”,P,S,myEOS.T_PS(P,S));
}
我不想让根查找器成为一个成员,因为它不是这个类特有的,而且使所有内容
都是静态的
的解决方案似乎非常不雅观。有人有主意吗?这一定是一个常见的情况,但我没有找到一个相关的职位,也可以理解我

谢谢


Edit:实际上,我还想问:除了我所做的之外,还有没有一种正确的线程安全的方法来设置
Pseek
变量?只是想说明一下:我正在对二维函数进行一维根查找,但修复了两个参数中的一个。

一种方法是更改根查找器的签名(添加
\include
):

这会带来一定的开销。如果您不介意有大量重复代码,可以将函数设置为模板:

template <typename Func>
double OneDimBisector(Func f, float a, float b, float tol);
template <typename F>
double OneDimBisector(F fun, float a, float b, float tol){
   double val;
   val = fun(0.5*(b-a));
   return val;                                                        
}
模板
双一维平分线(函数f、浮点a、浮点b、浮点tol);
以相同的方式调用它,但每次有新的函数类型时,都会在编译文件中创建一个新的模板实例

“传统”的解决方案是使用一个自由(或静态)函数来接受额外的实例参数


更新:传统解决方案:

double onedim平分线(double(*f)(浮点,void*),void*数据,…);
双EOS二等分(浮点f,空*数据)
{
EOS*e=static_cast(数据);//非常“传统”
返回e->functorForT\u PS(f);
}
用法:
T1=onedimDisector(eosDisect、this、Tmin、Tmax、tol)

一种方法是
template <typename Func>
double OneDimBisector(Func f, float a, float b, float tol);
double OneDimBisector(double(*f)(float, void *), void * data, ...);

double EOSBisect(float f, void * data)
{
    EOS * e = static_cast<EOS *>(data); // very "traditional"
    return e->functorForT_PS(f);
}
typedef boost::function<double (double)> MyFun;
double OneDimBisector(const MyFun & fun, float a, float b, float tol){
    double val;                                                                                                                                                                           
    val = fun(0.5*(b-a));    // actually: do proper bisection                                                                                                                          
    return val;                                                                                                                                                                           
}

// Calling
T1 = OneDimBisector (boost::bind (&EOS::functForT_PS, *this), Tmin, Tmax, tol));                                                                                                                                                                                      
template <typename F>
double OneDimBisector(F fun, float a, float b, float tol){
   double val;
   val = fun(0.5*(b-a));
   return val;                                                        
}
struct Evaluator
{
   EOS* this_;

   Evaluator(EOS* this_) : this_(this_) {}  // constructor

   double operator()(double value) const    // call the function
   {
       return this_->functForT_PS(value);
   }
};

T1 = OneDimBisector(Evaluator(this), Tmin, Tmax, tol);
double OneDimBisector(const boost::function<double(double)>& fun,
                      float a, float b, float tol)
{
    return fun(0.5 * (b-a));
}
T1 = OneDimBisector([=](double value){ return functForT_PS(value); },
                    Tmin, Tmax, tol);