如何制作一个typedef或用于指向类模板的方法指针?

问题描述

我有一个从Parent继承的对象,该对象创建了一个孩子。它给孩子一个std::function来报告状态,但是在实践中std:function可能永远是父对象上的方法,因此,为了方便起见,提供了一个额外的构造函数,将其作为参数

我已经制作了typedef中的std::function,但是我不知道如何制作方法指针的typedef

class Child { // No Hungarian: abstract class,so no variables of this type exist.
  
public:

  typedef std::function< void( Child* child_in,Msg* pmsg ) > FuncCB;

  // can't figure out some way to define an MethodCB.
  //template<T> typedef void (T::*MethodCB)( Child* child_in,Msg* pmsg );

  Child( Parent* pparent_in,FuncCB asynccb_in ) :
      pparent( pparent_in ),asynccb_( asynccb_in )
  {
  };

  template<typename T>
  // can't figure out some way to define an MethodCB.
  //Child( Parent* pparent_in,MethodCB pmethod_in ) :
  Child( Parent* pparent_in,void (T::*pmethod_in)() ) :
      Child( pparent_in,[=]( Child* pchild,Msg* pmsg )
                         { (pparent_in->*pmethod_in)( pchild,pmsg ); } )
  {
  };

  // Either way,the callback is stored here:
  FuncCB funccb;


     :
     :
  // When child wants to send a message to parent.  Generally the parent
  // will have a method to take this call,but it could technically be
  // any other std::function object type as well.

  funccb( this,Msg( "blah" ) );

解决方法

您的lambda不会接受任何参数,但是要匹配FuncCB的签名,它必须接受2个参数。修复lambda,您就可以开始了:

template <typename T>
using MemFunc = void (T::*) ();

using Func = std::function<void(Parent&,int msg)>;

template <typename T>
Child(T& parent,Func f)
{
    f(parent,10);
}

template <typename T>
Child(T& parent,MemFunc<T> f) :
    Child(parent,[f](Parent& p,int msg) { (p.*f)(); }) // note that the lambda takes 2 arguments here,and we don't use parent,but p to call the member function!
{        
}

Example

正如molbdnilo所指出的那样,如果T不是Parent以外的任何东西,这将不起作用。为了使这项工作有效,您必须将父对象强制转换为您要传入的任何派生类型。但这要求您仅传递类型为T的参数,否则将失败:

template <typename T>
Child(T& parent,int msg) { (dynamic_cast<T&>(p).*f)(); })
{        
}
,

为什么过度约束参数?

template <class T,class Fn>
Child (T* parent,Fn fun) : Child(parent,[=](Child* child,Msg* msg) {
                                    std::invoke(fun,parent,child,msg);
                                  }) 
{}

您也可以摆脱丑陋的lambda语法。

template <class T,std::bind(fun,_1,_2)) 
{}

是的,std::bind简单有趣。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...