将成员函数指针与参数包一起使用


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

最新更新