微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用带参数包的成员函数指针

如何解决使用带参数包的成员函数指针

template<typename Callback,typename Callee,typename... Args>
std::function<void(Args...)> safe_bind(Callback callback,std::shared_ptr<Callee> shared) {
    std::weak_ptr<Callee> weak = shared;
    return std::function<void(Args...)>([callback,weak](Args... args){
        if(auto shared_ptr = weak.lock()) {
            // std::bind(callback,ptr)(args...);
            // callback(ptr,args...);
            (shared_ptr.get()->*callback)(args...);
        }
    });
}

这个函数类似于std::bind,但是当绑定对象被销毁时,返回的函数可以安全地调用。 它无法编译,因为无法推导出 Args。我想关联 Callback = void(Args...)。但是,我找不到将 Callback 替换为带有参数包的 std::function 或函数指针类型的方法

safe_bind(Callback callback,std::shared_ptr<Callee> shared) {          // does not compile
safe_bind(void(*)(Callee*,Args...) callback,std::shared_ptr<Callee> shared) {  // does not compile
safe_bind((void(*)(Callee*,Args...)) callback,std::shared_ptr<Callee> shared) {// does not compile
...

如何实现? callback 将主要是 &Class::method,因此最好使用没有 std::function解决方案(如果可能)以避免分配。

解决方法

只是不要将 lambda 包装在 std::function 中并使用任何参数类型的完美转发。您还可以使用 std::invoke 处理其他可调用对象,它会自动处理带有 operator() 的指针成员(-函数)、函数和对象:

template<typename Callback,typename Callee>
auto safe_bind(Callback&& callback,std::shared_ptr<Callee> shared) {
    return [weak = std::weak_ptr{shared},callback = std::forward<Callback>(callback)](auto&&... args) {
        if (auto shared_ptr = weak.lock()) {
            std::invoke(callback,*shared_ptr,std::forward<decltype(args)>(args)...);
        }
    };
}

如果函数总是指向成员函数的指针,你可以从指针推导出参数的类型:

template<typename Callee,typename Res,typename... Args>
auto safe_bind(Res (Callee::* callback)(Args...),std::shared_ptr<Callee> shared) {
    return [weak = std::weak_ptr<Callee>{shared},callback](Args... args) {
        if (auto shared_ptr = weak.lock()) {
            // The std::forward here moves arguments that are passed by value
            ((*shared_ptr).*callback)(std::forward<Args>(args)...);
        }
    };
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。