问题描述
我有一个框架函数,它需要一个对象和一个成员函数指针(回调),如下所示:
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 ++中的成员函数指针传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!