将lambda表达式作为c ++中的成员函数指针传递

ivz*_*ave 5 c++ lambda function-pointers c++11

我有一个框架函数,它需要一个对象和一个成员函数指针(回调),如下所示:

do_some_work(Object* optr, void (Object::*fptr)()); // will call (optr->*fptr)()
Run Code Online (Sandbox Code Playgroud)

我怎样才能将lambda表达式传递给它?想做这样的事:

class MyObject : public Object
{
    void mystuff()
    {
        do_some_work(this, [](){ /* this lambda I want to pass */ });
    }
};
Run Code Online (Sandbox Code Playgroud)

这一切的意义是不要使用回调混乱MyObject类的接口.

UPD 我可以改进do_some_work,因为我不控制框架,因为实际上它不是一个函数,它有数百个.整个框架基于该类型的回调.没有lambda的常见用法示例:

typedef void (Object::*Callback)();
class MyObject : public Object
{
    void mystuff()
    {
        do_some_work(this, (Callback)(MyClass::do_work));
    }
    void do_work()
    {
        // here the work is done
    }
};
Run Code Online (Sandbox Code Playgroud)

解决方案这是基于Marcelo答案的解决方案:

class CallbackWrapper : public Object
{
    fptr fptr_;
public:
    CallbackWrapper(void (*fptr)()) : fptr_(fptr) { }
    void execute()
    {
        *fptr_();
    }
};

class MyObject : public Object
{
    void mystuff()
    {
        CallbackWrapper* do_work = new CallbackWrapper([]()
        {
           /* this lambda is passed */
        });
        do_some_work(do_work, (Callback)(CallbackWrapper::execute));
    }
};
Run Code Online (Sandbox Code Playgroud)

由于我们创建了CallbackWrapper,因此我们可以控制它的生命周期,以用于异步使用回调的情况.谢谢大家.

Mar*_*tos 6

这是不可能的.该构造(optr->*fptr)()要求fptr是指向成员的指针.如果do_some_work在您的控制之下,请将其更改为采用与lambda函数兼容的内容,例如std::function<void()>或参数化类型.如果它是一个不受您控制的遗留框架,您可以将其包装起来,如果它是一个功能模板,例如:

template <typename Object>
do_some_work(Object* optr, void (Object::*fptr)());
Run Code Online (Sandbox Code Playgroud)

然后,您可以实现包装器模板:

template <typename F>
void do_some_work(F f) {
    struct S {
        F f;
        S(F f) : f(f) { }
        void call() { f(); delete this; }
    };
    S* lamf = new S(f);
    do_some_work(lamf, &S::call);
}

class MyObject // You probably don't need this class anymore.
{
    void mystuff()
    {
        do_some_work([](){ /* Do your thing... */ });
    }
};
Run Code Online (Sandbox Code Playgroud)

编辑:如果do_some_work异步完成,则必须lamf在堆上进行分配.我相应地修改了上面的代码,只是为了安全起见.感谢@David Rodriguez指出这一点.