如何在函数声明中声明C++ mem_fn(member_function)?

Cha*_*les 6 c++ member-functions

我理解将成员函数的地址传递给它的类之外的基本问题.我觉得mem_fn()可能是解决方案,但我遇到了具体问题.

我在类p中有一个当前声明为的成员函数

typedef void (*valNamedFlagsCallback)(const int, const bool);
bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], valNamedFlagsCallback callBack);
Run Code Online (Sandbox Code Playgroud)

在课堂上我试图用valNamedFlags调用

pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::mem_fn(&e::setStatement));
Run Code Online (Sandbox Code Playgroud)

(我从没有mem_fn()开始,但当然有经典的"指向成员函数的指针"问题.我已经尝试了两个&e :: setStatement和plain&setStatement.)

FWIW,setStatement原型为

  void setStatement(const int ifcid, const bool isAffirmative);
Run Code Online (Sandbox Code Playgroud)

如果我删除mem_fn()并将setStatement声明为static,则一切正常.我只是指出这是一种说法,我已经消除了所有其他可能的问题; 我唯一的问题是"成员函数指针"问题.不幸的是,setStatement()需要是一个成员函数,而不是静态函数.

我在MS VS 2010中遇到的具体错误是

bool p :: valNamedFlags(const OptBlk*,const char*,const int [],const char*[],p :: valNamedFlagsCallback)':无法从'std :: tr1 :: _ Mem_fn3 <_Rx,_Pmf转换参数5, _Arg0,_Arg1,_Arg2>'到'p :: valNamedFlagsCallback'

我想保持回调声明独立于e类; 也就是说,我不想去

typedef void (*e::valNamedFlagsCallback)(const int, const bool);
Run Code Online (Sandbox Code Playgroud)

因为我想保持比这更普遍.

mem_fn()是正确的解决方案还是我离开基地?如果是这样,我应该如何在valNamedFlags()原型中声明回调?

或者我应该采用不同的方法?

Yam*_*vic 6

实际上,你会遇到像一些人建议的类似绑定的问题,因为你的回调被定义为一个简单的函数指针,而不是一个可调用的.

如果你能负担得起,你可以改变你的

typedef void (*valNamedFlagsCallback)(const int, const bool);
Run Code Online (Sandbox Code Playgroud)

喜欢的东西

typedef std::function<void(int, bool)> valNamedFlagsCallback
Run Code Online (Sandbox Code Playgroud)

(还注意到const值参数不影响函数的签名),那么你可以使用std::bind(),

using namespace std::placeholders;

pInstance->valNamedFlags(operand,
      "Statement types", 
      statementsSubscripts,
      statementsNames,
      std::bind(&E::setStatement, e, _1, _2));
Run Code Online (Sandbox Code Playgroud)

或者你可以使用lambdas:

pInstance->valNamedFlags(operand,
  "Statement types", 
  statementsSubscripts,
  statementsNames,
  [&](int i, bool b) { e->setStatement(i, b); });
Run Code Online (Sandbox Code Playgroud)

如果你必须将它保持为一个简单的函数,那么你必须发送一个引用正确对象作为全局/静态变量的函数.


son*_*yao 5

你需要bind一个实例来通过成员函数指针调用.(即std::bind(&e::setStatement, eInstance, _1, _2),假设eInstance是指向类对象的指针e).

using namespace std::placeholders;  // for _1, _2, _3...
pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::bind(&e::setStatement, eInstance, _1, _2));
Run Code Online (Sandbox Code Playgroud)

请注意,返回值std::bind(未指定)与自由函数指针类型不匹配valNamedFlagsCallback,其中一个解决方案是使用std::function.

typedef std::function<void(const int, const bool)> valNamedFlagsCallback;
Run Code Online (Sandbox Code Playgroud)

简化演示

  • @YamMarcovic - 好点.`valNamedFlags`必须将绑定表达式的结果作为其最终参数; 在实践中,这意味着它应该是一个模板,或者它应该采用`std :: function <void(int,bool)>`它当前需要`valNamedFlagsCallback`. (2认同)