【问题标题】:How to store parameter packed function for later called如何存储参数打包函数供以后调用
【发布时间】: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, &amp;args...],您可以通过引用捕获args由于已通过副本传递,因此您有悬空参考。
  • 为什么在 lambda 上使用 bindauto bind = [&amp;sp](auto&amp; obj){ sp.PostEvent(&amp;Test, obj); };
  • 你的SlotProxy已经存储带有参数包的函数调用以供以后调用(或者当您修复已经描述的悬空引用错误时它会这样做)。为什么要委托构造委托?只需立即调用SlotProxy::PostEvent,稍后在另一个线程中调用operator()

标签: c++


【解决方案1】:

问题(错误)是PostEvent是一个成员函数模板当它用作std::bind的参数时,如&amp;SlotProxy::PostEvent,其模板参数的类型是未知的。

这意味着我们需要使用默认参数或明确告诉编译器其模板参数的类型。下面是一个人为的例子:

template <typename T>
class myclass {
public:
  template<typename U>
  void func(const U&)
  {

  }
};
int main(){

  myclass<int> obj;
  //--------------------------------------------vvvvvv----------->pass the argument explicitly
  auto mylambda = std::bind(&myclass<int>::func<double>, &obj, 5);
  mylambda();

}

同样,您需要显式传递模板参数或尽可能使用默认参数。

您还应该注意代码可能存在的其他问题,例如悬挂引用等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多