问题描述
我有一个从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!
{
}
正如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
简单有趣。