【发布时间】:2022-11-23 00:30:56
【问题描述】:
我正在构建一个带有信号/槽库的项目,我希望能够在与调用它的信号不同的线程中执行槽,就像 Qt 那样。
为此,我试图存储一个带有参数包的函数调用以允许不同的参数编号:
#include <functional>
#include <iostream>
struct SlotProxy {
template<typename Func, typename ...Args>
void PostEvent(Func func, Args ... args) {
_callback = [func, &args...]() {
func(args...);
};
}
void operator()() {
_callback();
}
std::function<void()> _callback;
};
struct Obj {
int i{};
void Print() {
std::cout << this << " - Obj val : " << i << std::endl;
}
void Slot(Obj& obj) {
obj.Print();
}
};
void Test(Obj& obj) {
obj.Print();
}
int main() {
Obj obj{};
obj.Print();
SlotProxy sp{};
// error : no matching call for bind
auto bind = std::bind(&SlotProxy::PostEvent, &sp, &Test, std::placeholders::_1);
bind(obj);
}
这里 std::bind 给我一个错误,它找不到匹配的定义,我做错了什么?
附属问题:如何将成员函数作为参数绑定到 Post Event?做一个 嵌套的 std::bind 会工作吗?
std::bind(&SlotProxy::PostEvent, &p, std::bind(&Obj::Slot, obj, ???), std::placeholders::_1);
【问题讨论】:
-
使用
[func, &args...],您可以通过引用捕获args,但由于已通过副本传递,因此您有悬空参考。 -
为什么在 lambda 上使用
bind?auto bind = [&sp](auto& obj){ sp.PostEvent(&Test, obj); };? -
你的
SlotProxy已经存储带有参数包的函数调用以供以后调用(或者当您修复已经描述的悬空引用错误时它会这样做)。为什么要委托构造委托?只需立即调用SlotProxy::PostEvent,稍后在另一个线程中调用operator()。
标签: c++