本文介绍了将Lambda表达式作为C ++中的成员函数指针传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a framework function which expects an object and a member function pointer (callback), like this:

do_some_work(Object* optr, void (Object::*fptr)()); // will call (optr->*fptr)()

如何传递Lambda表达式要吗?想要这样想:

How can I pass a lambda expression to it? Want to do somethink like this:

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

这一切的含义是不要使MyObject类的接口与回调混杂在一起。

The meaning of it all is to not clutter the interface of MyObject class with callbacks.

UPD
我无法改善 do_some_work ,因为我无法控制框架因为实际上这不是一项功能,所以有数百种功能。整个框架基于该类型的回调。不带lambda的常见用法示例:

UPDI can improve do_some_work in no way because I don't control framework and because actually it isn't one function, there're hundreds of them. Whole framework is based on callbacks of that type. Common usage example without lambdas:

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
    }
};

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

SOLUTION Here's my solution based on Marcelo's answer:

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));
    }
};

自从我们创建CallbackWrapper以来,我们可以控制异步使用回调的时间。谢谢大家。

Since we create the CallbackWrapper we can control it's lifetime for the cases where the callback is used asynchonously. Thanks to all.

推荐答案

这是不可能的。构造(optr-> * fptr)()要求fptr是指向成员的指针。如果 do_some_work 在您的控制之下,请更改它以使其与lambda函数兼容,例如 std :: function< void()> 或参数化类型。如果它是不受您控制的旧框架,则可以包装它,如果它是功能模板,例如:

This is impossible. The construct (optr->*fptr)() requires that fptr be a pointer-to-member. If do_some_work is under your control, change it to take something that's compatible with a lambda function, such as std::function<void()> or a parameterised type. If it's a legacy framework that isn't under your control, you may be able to wrap it, if it's a function template, e.g.:

template <typename Object>
do_some_work(Object* optr, void (Object::*fptr)());

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

Then, you can implement a wrapper template:

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... */ });
    }
};

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

If do_some_work completes asynchronously, you must allocate lamf on the heap. I've amended the above code accordingly, just to be on the safe side. Thanks to @David Rodriguez for pointing this out.

这篇关于将Lambda表达式作为C ++中的成员函数指针传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-24 17:00