#pragma once #include #include #include namespace fastsignals { namespace detail { template struct weak_binder { using ConstMethodType = ReturnType (ClassType::*)(Args... args) const; using NonConstMethodType = ReturnType (ClassType::*)(Args... args); using MethodType = std::conditional_t; using WeakPtrType = std::weak_ptr; weak_binder(MethodType pMethod, WeakPtrType&& pObject) : m_pMethod(pMethod) , m_pObject(std::move(pObject)) { } ReturnType operator()(Args... args) const { if (auto pThis = m_pObject.lock()) { return (pThis.get()->*m_pMethod)(std::forward(args)...); } return ReturnType(); } MethodType m_pMethod; WeakPtrType m_pObject; }; } // namespace detail /// Weak this binding of non-const methods. template decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args), std::shared_ptr const& pThis, Args... args) { using weak_binder_alias = detail::weak_binder; weak_binder_alias invoker(memberFn, std::weak_ptr(pThis)); return std::bind(invoker, args...); } /// Weak this binding of const methods. template decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args) const, std::shared_ptr const& pThis, Args... args) { using weak_binder_alias = detail::weak_binder; weak_binder_alias invoker(memberFn, std::weak_ptr(pThis)); return std::bind(invoker, args...); } /// Weak this binding of non-const methods. template decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args), std::weak_ptr pThis, Args... args) { using weak_binder_alias = detail::weak_binder; weak_binder_alias invoker(memberFn, std::move(pThis)); return std::bind(invoker, args...); } /// Weak this binding of const methods. template decltype(auto) bind_weak(ReturnType (ClassType::*memberFn)(Params... args) const, std::weak_ptr pThis, Args... args) { using weak_binder_alias = detail::weak_binder; weak_binder_alias invoker(memberFn, std::move(pThis)); return std::bind(invoker, args...); } } // namespace fastsignals